mirror of
https://github.com/bilawalsidhu/gods-eye-view.git
synced 2026-11-04 02:14:01 +00:00
The kit's comments and docs describe its props and classes directly instead of by reference to another kit.
68 lines
2.6 KiB
JavaScript
68 lines
2.6 KiB
JavaScript
import { h, mergeProps, nextTick, withDirectives } from 'vue';
|
|
import { vFieldValue } from '../rail/fieldValue.js';
|
|
import { vRangeValue } from '../rail/rangeValue.js';
|
|
|
|
// A null model leaves the select as it is.
|
|
const live = (el, binding) => {
|
|
if (binding.value != null) vRangeValue.updated(el, binding);
|
|
};
|
|
const LIVE = { mounted: live, updated: live };
|
|
|
|
/** Put the model back on the select. */
|
|
function takeModel(select, props) {
|
|
const next = props.modelValue;
|
|
if (next != null && select.value !== String(next))
|
|
select.value = String(next);
|
|
}
|
|
|
|
/**
|
|
* Core's select, with v-model, options and disabled. Core renders the bare select: its
|
|
* labels sit outside it or come as an `aria-label` attribute, so the attribute
|
|
* pass translates them. Options come from `options` ({ value, label }) or,
|
|
* where they carry their own attributes, the default slot. A change emits the
|
|
* chosen value; a caller's own `@change` still reaches the select.
|
|
*
|
|
* The select takes the model's value only when it differs (`v-range-value`),
|
|
* after its options are in place; a null model leaves it as it is. With
|
|
* `hold`, it never takes it while focused (`v-field-value`), and takes it back
|
|
* when it loses focus. Without `hold`, it takes the model back once the
|
|
* change's render has run: an owner that refuses a pick republishes the same
|
|
* value, which renders nothing, so this puts the refused pick back. The
|
|
* owners of these selects answer synchronously. Like UiSlider it is a functional render-function
|
|
* component. Not mirrored yet: `label` and `hideLabel`.
|
|
*/
|
|
export default function UiSelect(props, { attrs, emit, slots }) {
|
|
const options = props.options
|
|
? props.options.map((option) =>
|
|
h('option', { key: option.value, value: option.value }, option.label),
|
|
)
|
|
: slots.default?.();
|
|
const select = h(
|
|
'select',
|
|
mergeProps(attrs, {
|
|
disabled: props.disabled,
|
|
onChange: (event) => {
|
|
const select = event.target;
|
|
emit('update:modelValue', select.value);
|
|
if (!props.hold) void nextTick(() => takeModel(select, props));
|
|
},
|
|
onBlur: props.hold
|
|
? (event) => takeModel(event.target, props)
|
|
: undefined,
|
|
}),
|
|
options,
|
|
);
|
|
return withDirectives(select, [
|
|
[props.hold ? vFieldValue : LIVE, props.modelValue],
|
|
]);
|
|
}
|
|
|
|
UiSelect.props = {
|
|
modelValue: { type: [String, Number], default: undefined },
|
|
options: { type: Array, default: undefined },
|
|
disabled: { type: Boolean, default: false },
|
|
hold: { type: Boolean, default: false },
|
|
};
|
|
UiSelect.emits = ['update:modelValue'];
|
|
UiSelect.inheritAttrs = false;
|