@sewadah/selaras 0.9.0 → 0.10.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +11 -0
- package/dist/agent/catalog.json +1 -1
- package/dist/module.json +1 -1
- package/dist/runtime/components/Checkbox.d.vue.ts +6 -4
- package/dist/runtime/components/Checkbox.vue +30 -22
- package/dist/runtime/components/Checkbox.vue.d.ts +6 -4
- package/dist/runtime/components/DatePicker.d.vue.ts +27 -27
- package/dist/runtime/components/DatePicker.vue +58 -99
- package/dist/runtime/components/DatePicker.vue.d.ts +27 -27
- package/dist/runtime/components/Editable.d.vue.ts +91 -0
- package/dist/runtime/components/Editable.vue +257 -0
- package/dist/runtime/components/Editable.vue.d.ts +91 -0
- package/dist/runtime/components/Input.vue +21 -22
- package/dist/runtime/components/Textarea.vue +20 -23
- package/dist/runtime/components/Toolbar.d.vue.ts +25 -0
- package/dist/runtime/components/Toolbar.vue +35 -0
- package/dist/runtime/components/Toolbar.vue.d.ts +25 -0
- package/dist/runtime/components/ToolbarButton.d.vue.ts +20 -0
- package/dist/runtime/components/ToolbarButton.vue +46 -0
- package/dist/runtime/components/ToolbarButton.vue.d.ts +20 -0
- package/dist/runtime/components/ToolbarSeparator.d.vue.ts +10 -0
- package/dist/runtime/components/ToolbarSeparator.vue +22 -0
- package/dist/runtime/components/ToolbarSeparator.vue.d.ts +10 -0
- package/dist/runtime/components/ToolbarToggleGroup.d.vue.ts +37 -0
- package/dist/runtime/components/ToolbarToggleGroup.vue +44 -0
- package/dist/runtime/components/ToolbarToggleGroup.vue.d.ts +37 -0
- package/dist/runtime/internal/ComboboxSelectBase.vue +41 -50
- package/dist/runtime/internal/FieldClearButton.d.vue.ts +21 -0
- package/dist/runtime/internal/FieldClearButton.vue +30 -0
- package/dist/runtime/internal/FieldClearButton.vue.d.ts +21 -0
- package/dist/runtime/internal/ListboxOption.d.vue.ts +2 -1
- package/dist/runtime/internal/ListboxOption.vue +3 -2
- package/dist/runtime/internal/ListboxOption.vue.d.ts +2 -1
- package/dist/runtime/theme/date-picker.d.ts +27 -0
- package/dist/runtime/theme/date-picker.js +6 -3
- package/dist/runtime/theme/editable.d.ts +155 -0
- package/dist/runtime/theme/editable.js +25 -0
- package/dist/runtime/theme/field-clear-button.d.ts +56 -0
- package/dist/runtime/theme/field-clear-button.js +15 -0
- package/dist/runtime/theme/input.d.ts +0 -9
- package/dist/runtime/theme/input.js +5 -12
- package/dist/runtime/theme/listbox.js +1 -1
- package/dist/runtime/theme/select.d.ts +9 -0
- package/dist/runtime/theme/select.js +11 -10
- package/dist/runtime/theme/textarea.d.ts +0 -9
- package/dist/runtime/theme/textarea.js +4 -4
- package/dist/runtime/theme/toolbar-button.d.ts +65 -0
- package/dist/runtime/theme/toolbar-button.js +21 -0
- package/dist/runtime/theme/toolbar-separator.d.ts +35 -0
- package/dist/runtime/theme/toolbar-separator.js +8 -0
- package/dist/runtime/theme/toolbar-toggle-group.d.ts +74 -0
- package/dist/runtime/theme/toolbar-toggle-group.js +13 -0
- package/dist/runtime/theme/toolbar.d.ts +35 -0
- package/dist/runtime/theme/toolbar.js +11 -0
- package/dist/runtime/theme-config.d.ts +36 -0
- package/dist/runtime/types/index.d.ts +5 -0
- package/dist/runtime/utils/field-clear.d.ts +9 -0
- package/dist/runtime/utils/field-clear.js +7 -0
- package/dist/runtime/utils/icons.d.ts +1 -0
- package/dist/runtime/utils/icons.js +1 -0
- package/dist/runtime/utils/messages.d.ts +4 -0
- package/dist/runtime/utils/messages.js +4 -0
- package/dist/runtime/utils/toolbar.d.ts +9 -0
- package/dist/runtime/utils/toolbar.js +1 -0
- package/package.json +9 -2
- package/skills/selaras/SKILL.md +4 -0
package/dist/module.json
CHANGED
|
@@ -14,6 +14,8 @@ export interface CheckboxProps {
|
|
|
14
14
|
disabled?: boolean;
|
|
15
15
|
invalid?: boolean;
|
|
16
16
|
required?: boolean;
|
|
17
|
+
/** Renders only the visual indicator, without a focus target, form input, or inherited FormField state. Selection is owned by the surrounding control. */
|
|
18
|
+
decorative?: boolean;
|
|
17
19
|
size?: CheckboxVariants['size'];
|
|
18
20
|
color?: ColorRole;
|
|
19
21
|
/** `card` wraps the checkbox and label in a bordered box, highlighted when checked - the same treatment RadioGroup's own `card` variant already applies per item. */
|
|
@@ -23,13 +25,13 @@ export interface CheckboxProps {
|
|
|
23
25
|
export interface CheckboxEmits {
|
|
24
26
|
'update:modelValue': [value: boolean | 'indeterminate'];
|
|
25
27
|
}
|
|
26
|
-
declare var
|
|
28
|
+
declare var __VLS_20: {}, __VLS_22: {}, __VLS_24: {};
|
|
27
29
|
type __VLS_Slots = {} & {
|
|
28
|
-
default?: (props: typeof
|
|
30
|
+
default?: (props: typeof __VLS_20) => any;
|
|
29
31
|
} & {
|
|
30
|
-
description?: (props: typeof
|
|
32
|
+
description?: (props: typeof __VLS_22) => any;
|
|
31
33
|
} & {
|
|
32
|
-
default?: (props: typeof
|
|
34
|
+
default?: (props: typeof __VLS_24) => any;
|
|
33
35
|
};
|
|
34
36
|
declare const __VLS_base: import("vue").DefineComponent<CheckboxProps, {}, {}, {}, {}, import("vue").ComponentOptionsMixin, import("vue").ComponentOptionsMixin, {
|
|
35
37
|
"update:modelValue": (value: boolean | "indeterminate") => any;
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
<script setup>
|
|
2
2
|
import { CheckboxIndicator, CheckboxRoot } from "reka-ui";
|
|
3
|
-
import { computed } from "vue";
|
|
3
|
+
import { computed, mergeProps } from "vue";
|
|
4
4
|
import { useFormField } from "../composables/use-form-field";
|
|
5
5
|
import { checkboxTheme } from "../theme/checkbox";
|
|
6
6
|
import { resolveRegisteredColorRole } from "../utils/registered-colors";
|
|
@@ -15,17 +15,19 @@ const props = defineProps({
|
|
|
15
15
|
disabled: { type: Boolean, required: false },
|
|
16
16
|
invalid: { type: Boolean, required: false },
|
|
17
17
|
required: { type: Boolean, required: false },
|
|
18
|
+
decorative: { type: Boolean, required: false },
|
|
18
19
|
size: { type: null, required: false },
|
|
19
20
|
color: { type: null, required: false },
|
|
20
21
|
variant: { type: null, required: false },
|
|
21
22
|
ui: { type: Object, required: false }
|
|
22
23
|
});
|
|
23
24
|
const emit = defineEmits(["update:modelValue"]);
|
|
24
|
-
const
|
|
25
|
-
const
|
|
26
|
-
const
|
|
27
|
-
const
|
|
28
|
-
const
|
|
25
|
+
const inheritedField = useFormField();
|
|
26
|
+
const field = computed(() => props.decorative ? void 0 : inheritedField);
|
|
27
|
+
const checkboxId = computed(() => props.id ?? field.value?.id);
|
|
28
|
+
const checkboxInvalid = computed(() => props.invalid || (field.value?.invalid.value ?? false));
|
|
29
|
+
const effectiveSize = computed(() => props.size ?? field.value?.size ?? "md");
|
|
30
|
+
const describedBy = computed(() => field.value?.describedBy.value);
|
|
29
31
|
const theme = useComponentTheme("checkbox", checkboxTheme);
|
|
30
32
|
const effectiveColor = computed(() => resolveRegisteredColorRole(props.color ?? "primary", "primary"));
|
|
31
33
|
const ui = computed(() => theme.value({
|
|
@@ -43,28 +45,34 @@ const descriptionProps = computed(() => resolveSlot(ui.value.description, props.
|
|
|
43
45
|
const checkIconProps = computed(() => resolveSlot(ui.value.checkIcon, props.ui?.checkIcon));
|
|
44
46
|
const indeterminateIconProps = computed(() => resolveSlot(ui.value.indeterminateIcon, props.ui?.indeterminateIcon));
|
|
45
47
|
const glyphState = computed(() => props.modelValue === "indeterminate" ? "indeterminate" : props.modelValue ? "checked" : "unchecked");
|
|
48
|
+
const controlProps = computed(() => props.decorative ? {
|
|
49
|
+
...boxProps.value,
|
|
50
|
+
"data-state": glyphState.value,
|
|
51
|
+
"data-disabled": props.disabled ? "" : void 0
|
|
52
|
+
} : mergeProps({
|
|
53
|
+
"id": checkboxId.value,
|
|
54
|
+
"modelValue": props.modelValue,
|
|
55
|
+
"name": props.name ?? field.value?.name,
|
|
56
|
+
"disabled": props.disabled,
|
|
57
|
+
"required": props.required,
|
|
58
|
+
"aria-invalid": checkboxInvalid.value || void 0,
|
|
59
|
+
"aria-describedby": describedBy.value
|
|
60
|
+
}, boxProps.value, {
|
|
61
|
+
"onUpdate:modelValue": (value) => emit("update:modelValue", value)
|
|
62
|
+
}));
|
|
63
|
+
const visualIndicatorProps = computed(() => props.decorative ? { "data-state": glyphState.value, "data-disabled": props.disabled ? "" : void 0, ...indicatorProps.value } : { forceMount: true, ...indicatorProps.value });
|
|
46
64
|
</script>
|
|
47
65
|
|
|
48
66
|
<template>
|
|
49
|
-
<label :data-selaras-color="checkboxInvalid ? 'danger' : effectiveColor" v-bind="rootProps">
|
|
50
|
-
<CheckboxRoot
|
|
51
|
-
:
|
|
52
|
-
:model-value="modelValue"
|
|
53
|
-
:name="name ?? field?.name"
|
|
54
|
-
:disabled="disabled"
|
|
55
|
-
:required="required"
|
|
56
|
-
:aria-invalid="checkboxInvalid || void 0"
|
|
57
|
-
:aria-describedby="describedBy"
|
|
58
|
-
v-bind="boxProps"
|
|
59
|
-
@update:model-value="(value) => emit('update:modelValue', value)"
|
|
60
|
-
>
|
|
61
|
-
<CheckboxIndicator force-mount v-bind="indicatorProps">
|
|
67
|
+
<component :is="decorative ? 'span' : 'label'" :data-selaras-color="checkboxInvalid ? 'danger' : effectiveColor" v-bind="rootProps" :aria-hidden="decorative ? true : rootProps['aria-hidden']">
|
|
68
|
+
<component :is="decorative ? 'span' : CheckboxRoot" v-bind="controlProps">
|
|
69
|
+
<component :is="decorative ? 'span' : CheckboxIndicator" v-bind="visualIndicatorProps">
|
|
62
70
|
<svg viewBox="0 0 24 24" :class="applyClassPrefix('size-full')" fill="none" stroke="currentColor" stroke-width="2.5" stroke-linecap="round" stroke-linejoin="round">
|
|
63
71
|
<path d="M5 13l4 4L19 7" :data-state="glyphState" v-bind="checkIconProps" />
|
|
64
72
|
<path d="M5 12h14" :data-state="glyphState" v-bind="indeterminateIconProps" />
|
|
65
73
|
</svg>
|
|
66
|
-
</
|
|
67
|
-
</
|
|
74
|
+
</component>
|
|
75
|
+
</component>
|
|
68
76
|
<span v-if="description" v-bind="labelGroupProps">
|
|
69
77
|
<span v-if="label || $slots.default" v-bind="labelProps"><slot>{{ label }}</slot></span>
|
|
70
78
|
<span v-bind="descriptionProps">
|
|
@@ -74,5 +82,5 @@ const glyphState = computed(() => props.modelValue === "indeterminate" ? "indete
|
|
|
74
82
|
<span v-else-if="label || $slots.default" v-bind="labelProps">
|
|
75
83
|
<slot>{{ label }}</slot>
|
|
76
84
|
</span>
|
|
77
|
-
</
|
|
85
|
+
</component>
|
|
78
86
|
</template>
|
|
@@ -14,6 +14,8 @@ export interface CheckboxProps {
|
|
|
14
14
|
disabled?: boolean;
|
|
15
15
|
invalid?: boolean;
|
|
16
16
|
required?: boolean;
|
|
17
|
+
/** Renders only the visual indicator, without a focus target, form input, or inherited FormField state. Selection is owned by the surrounding control. */
|
|
18
|
+
decorative?: boolean;
|
|
17
19
|
size?: CheckboxVariants['size'];
|
|
18
20
|
color?: ColorRole;
|
|
19
21
|
/** `card` wraps the checkbox and label in a bordered box, highlighted when checked - the same treatment RadioGroup's own `card` variant already applies per item. */
|
|
@@ -23,13 +25,13 @@ export interface CheckboxProps {
|
|
|
23
25
|
export interface CheckboxEmits {
|
|
24
26
|
'update:modelValue': [value: boolean | 'indeterminate'];
|
|
25
27
|
}
|
|
26
|
-
declare var
|
|
28
|
+
declare var __VLS_20: {}, __VLS_22: {}, __VLS_24: {};
|
|
27
29
|
type __VLS_Slots = {} & {
|
|
28
|
-
default?: (props: typeof
|
|
30
|
+
default?: (props: typeof __VLS_20) => any;
|
|
29
31
|
} & {
|
|
30
|
-
description?: (props: typeof
|
|
32
|
+
description?: (props: typeof __VLS_22) => any;
|
|
31
33
|
} & {
|
|
32
|
-
default?: (props: typeof
|
|
34
|
+
default?: (props: typeof __VLS_24) => any;
|
|
33
35
|
};
|
|
34
36
|
declare const __VLS_base: import("vue").DefineComponent<CheckboxProps, {}, {}, {}, {}, import("vue").ComponentOptionsMixin, import("vue").ComponentOptionsMixin, {
|
|
35
37
|
"update:modelValue": (value: boolean | "indeterminate") => any;
|
|
@@ -69,7 +69,7 @@ export interface DatePickerProps {
|
|
|
69
69
|
isYearDisabled?: (year: number) => boolean;
|
|
70
70
|
invalid?: boolean;
|
|
71
71
|
clearable?: boolean;
|
|
72
|
-
/** Chrome color
|
|
72
|
+
/** Chrome color for trigger buttons and calendar navigation. Clear controls remain neutral. */
|
|
73
73
|
color?: ColorRole;
|
|
74
74
|
/** The color of whatever's currently "active" - the selected day/month/year cell and the Done button. */
|
|
75
75
|
activeColor?: ColorRole;
|
|
@@ -90,7 +90,7 @@ export interface DatePickerEmits {
|
|
|
90
90
|
'update:modelValue': [value: DateValue | DateRange | Time | undefined];
|
|
91
91
|
'update:view': [view: 'date' | 'month' | 'year'];
|
|
92
92
|
}
|
|
93
|
-
declare var __VLS_43: {},
|
|
93
|
+
declare var __VLS_43: {}, __VLS_58: {}, __VLS_80: {}, __VLS_96: {}, __VLS_111: {
|
|
94
94
|
date: DateValue;
|
|
95
95
|
dayValue: string;
|
|
96
96
|
selected: boolean;
|
|
@@ -98,7 +98,7 @@ declare var __VLS_43: {}, __VLS_63: {}, __VLS_83: {}, __VLS_99: {}, __VLS_119: {
|
|
|
98
98
|
selectionStart: boolean;
|
|
99
99
|
selectionEnd: boolean;
|
|
100
100
|
highlighted: boolean;
|
|
101
|
-
},
|
|
101
|
+
}, __VLS_114: {}, __VLS_137: {
|
|
102
102
|
date: DateValue;
|
|
103
103
|
dayValue: string;
|
|
104
104
|
selected: boolean;
|
|
@@ -106,61 +106,61 @@ declare var __VLS_43: {}, __VLS_63: {}, __VLS_83: {}, __VLS_99: {}, __VLS_119: {
|
|
|
106
106
|
selectionStart: boolean;
|
|
107
107
|
selectionEnd: boolean;
|
|
108
108
|
highlighted: boolean;
|
|
109
|
-
},
|
|
109
|
+
}, __VLS_140: {}, __VLS_179: {}, __VLS_194: {}, __VLS_216: {}, __VLS_232: {}, __VLS_253: {}, __VLS_276: {}, __VLS_314: {}, __VLS_329: {}, __VLS_351: {}, __VLS_367: {}, __VLS_382: {
|
|
110
110
|
date: DateValue;
|
|
111
111
|
dayValue: string;
|
|
112
112
|
selected: boolean;
|
|
113
113
|
disabled: boolean;
|
|
114
|
-
},
|
|
114
|
+
}, __VLS_385: {}, __VLS_408: {
|
|
115
115
|
date: DateValue;
|
|
116
116
|
dayValue: string;
|
|
117
117
|
selected: boolean;
|
|
118
118
|
disabled: boolean;
|
|
119
|
-
},
|
|
119
|
+
}, __VLS_411: {};
|
|
120
120
|
type __VLS_Slots = {} & {
|
|
121
121
|
'clear-icon'?: (props: typeof __VLS_43) => any;
|
|
122
122
|
} & {
|
|
123
|
-
'trigger-icon'?: (props: typeof
|
|
123
|
+
'trigger-icon'?: (props: typeof __VLS_58) => any;
|
|
124
124
|
} & {
|
|
125
|
-
'trigger-icon'?: (props: typeof
|
|
125
|
+
'trigger-icon'?: (props: typeof __VLS_80) => any;
|
|
126
126
|
} & {
|
|
127
|
-
'clear-icon'?: (props: typeof
|
|
127
|
+
'clear-icon'?: (props: typeof __VLS_96) => any;
|
|
128
128
|
} & {
|
|
129
|
-
day?: (props: typeof
|
|
129
|
+
day?: (props: typeof __VLS_111) => any;
|
|
130
130
|
} & {
|
|
131
|
-
footer?: (props: typeof
|
|
131
|
+
footer?: (props: typeof __VLS_114) => any;
|
|
132
132
|
} & {
|
|
133
|
-
day?: (props: typeof
|
|
133
|
+
day?: (props: typeof __VLS_137) => any;
|
|
134
134
|
} & {
|
|
135
|
-
footer?: (props: typeof
|
|
135
|
+
footer?: (props: typeof __VLS_140) => any;
|
|
136
136
|
} & {
|
|
137
|
-
'clear-icon'?: (props: typeof
|
|
137
|
+
'clear-icon'?: (props: typeof __VLS_179) => any;
|
|
138
138
|
} & {
|
|
139
|
-
'trigger-icon'?: (props: typeof
|
|
139
|
+
'trigger-icon'?: (props: typeof __VLS_194) => any;
|
|
140
140
|
} & {
|
|
141
|
-
'trigger-icon'?: (props: typeof
|
|
141
|
+
'trigger-icon'?: (props: typeof __VLS_216) => any;
|
|
142
142
|
} & {
|
|
143
|
-
'clear-icon'?: (props: typeof
|
|
143
|
+
'clear-icon'?: (props: typeof __VLS_232) => any;
|
|
144
144
|
} & {
|
|
145
|
-
footer?: (props: typeof
|
|
145
|
+
footer?: (props: typeof __VLS_253) => any;
|
|
146
146
|
} & {
|
|
147
|
-
footer?: (props: typeof
|
|
147
|
+
footer?: (props: typeof __VLS_276) => any;
|
|
148
148
|
} & {
|
|
149
|
-
'clear-icon'?: (props: typeof
|
|
149
|
+
'clear-icon'?: (props: typeof __VLS_314) => any;
|
|
150
150
|
} & {
|
|
151
|
-
'trigger-icon'?: (props: typeof
|
|
151
|
+
'trigger-icon'?: (props: typeof __VLS_329) => any;
|
|
152
152
|
} & {
|
|
153
|
-
'trigger-icon'?: (props: typeof
|
|
153
|
+
'trigger-icon'?: (props: typeof __VLS_351) => any;
|
|
154
154
|
} & {
|
|
155
|
-
'clear-icon'?: (props: typeof
|
|
155
|
+
'clear-icon'?: (props: typeof __VLS_367) => any;
|
|
156
156
|
} & {
|
|
157
|
-
day?: (props: typeof
|
|
157
|
+
day?: (props: typeof __VLS_382) => any;
|
|
158
158
|
} & {
|
|
159
|
-
footer?: (props: typeof
|
|
159
|
+
footer?: (props: typeof __VLS_385) => any;
|
|
160
160
|
} & {
|
|
161
|
-
day?: (props: typeof
|
|
161
|
+
day?: (props: typeof __VLS_408) => any;
|
|
162
162
|
} & {
|
|
163
|
-
footer?: (props: typeof
|
|
163
|
+
footer?: (props: typeof __VLS_411) => any;
|
|
164
164
|
};
|
|
165
165
|
declare const __VLS_base: import("vue").DefineComponent<DatePickerProps, {}, {}, {}, {}, import("vue").ComponentOptionsMixin, import("vue").ComponentOptionsMixin, {
|
|
166
166
|
"update:modelValue": (value: DateValue | DateRange | Time | undefined) => any;
|
|
@@ -24,7 +24,7 @@ import {
|
|
|
24
24
|
TimeFieldInput,
|
|
25
25
|
TimeFieldRoot
|
|
26
26
|
} from "reka-ui";
|
|
27
|
-
import { computed, getCurrentInstance, onMounted, onUnmounted, ref, shallowRef, useId, watch } from "vue";
|
|
27
|
+
import { computed, getCurrentInstance, mergeProps, nextTick, onMounted, onUnmounted, ref, shallowRef, useId, watch } from "vue";
|
|
28
28
|
import { useFormField } from "../composables/use-form-field";
|
|
29
29
|
import { useIcons } from "../composables/use-icons";
|
|
30
30
|
import { useLocale } from "../composables/use-locale";
|
|
@@ -33,8 +33,10 @@ import { useMessages } from "../composables/use-messages";
|
|
|
33
33
|
import DatePickerCalendarBody from "../internal/DatePickerCalendarBody.vue";
|
|
34
34
|
import DatePickerRangeCalendarBody from "../internal/DatePickerRangeCalendarBody.vue";
|
|
35
35
|
import DatePickerTimeBody from "../internal/DatePickerTimeBody.vue";
|
|
36
|
+
import FieldClearButton from "../internal/FieldClearButton.vue";
|
|
36
37
|
import { datePickerTheme } from "../theme/date-picker";
|
|
37
38
|
import { arrowContentProps, arrowElementProps } from "../utils/arrow";
|
|
39
|
+
import { canClearField, fieldClearWidths } from "../utils/field-clear";
|
|
38
40
|
import { overlayPortalProps } from "../utils/overlay";
|
|
39
41
|
import { resolveRegisteredColorRole } from "../utils/registered-colors";
|
|
40
42
|
import { applyClassPrefix, resolveSlot, useComponentTheme, useRootProps, useThemeBindings } from "../utils/ui";
|
|
@@ -137,8 +139,18 @@ const effectiveNumberOfMonths = computed(() => props.numberOfMonths ?? (props.ra
|
|
|
137
139
|
const singleModelValue = computed(() => props.range ? void 0 : modelValue.value);
|
|
138
140
|
const rangeModelValue = computed(() => props.range ? modelValue.value : void 0);
|
|
139
141
|
const hasValue = computed(() => props.range ? !!modelValue.value?.start : !!modelValue.value);
|
|
140
|
-
|
|
142
|
+
const showClear = computed(() => canClearField(props.clearable, props.range ? !!(modelValue.value?.start || modelValue.value?.end) : !!modelValue.value, props.disabled, props.readonly));
|
|
143
|
+
const fieldElement = ref();
|
|
144
|
+
const buttonTrigger = ref();
|
|
145
|
+
async function clear() {
|
|
146
|
+
if (!showClear.value)
|
|
147
|
+
return;
|
|
141
148
|
updateModelValue(props.range ? { start: void 0, end: void 0 } : void 0);
|
|
149
|
+
await nextTick();
|
|
150
|
+
if (props.triggerMode === "button")
|
|
151
|
+
buttonTrigger.value?.$el?.focus();
|
|
152
|
+
else
|
|
153
|
+
fieldElement.value?.querySelector("[role=spinbutton]")?.focus();
|
|
142
154
|
}
|
|
143
155
|
const defaultView = computed(() => {
|
|
144
156
|
if (props.granularity === "month" || props.granularity === "year")
|
|
@@ -364,6 +376,10 @@ const rootProps = useRootProps(() => ui.value.root, () => props.ui?.root);
|
|
|
364
376
|
const fieldProps = computed(() => resolveSlot(ui.value.field, props.ui?.field));
|
|
365
377
|
const segmentProps = computed(() => resolveSlot(ui.value.segment, props.ui?.segment));
|
|
366
378
|
const separatorProps = computed(() => resolveSlot(ui.value.separator, props.ui?.separator));
|
|
379
|
+
const clearProps = computed(() => resolveSlot(ui.value.clear, props.ui?.clear));
|
|
380
|
+
const buttonClearProps = computed(() => resolveSlot(ui.value.buttonClear, props.ui?.buttonClear));
|
|
381
|
+
const triggerIconProps = computed(() => resolveSlot(ui.value.triggerIcon, props.ui?.triggerIcon));
|
|
382
|
+
const buttonLabelStyle = computed(() => showClear.value ? { paddingInlineEnd: `calc(${fieldClearWidths[effectiveSize.value]} + 0.25rem)` } : void 0);
|
|
367
383
|
const contentProps = computed(() => ({ ...resolveSlot(ui.value.content, props.ui?.content), ...arrowContentProps(props.arrow), ...props.positioning }));
|
|
368
384
|
const portalProps = computed(() => overlayPortalProps(props.portal));
|
|
369
385
|
const arrowProps = computed(() => ({ ...resolveSlot(ui.value.arrow, props.ui?.arrow), ...arrowElementProps(props.arrow) }));
|
|
@@ -451,10 +467,7 @@ const timeBodyProps = computed(() => ({
|
|
|
451
467
|
const buttonTriggerUi = computed(() => ({
|
|
452
468
|
base: [
|
|
453
469
|
"w-full justify-start rounded-[var(--selaras-resolved-radius-md)] bg-[var(--selaras-resolved-surface-default)] text-[var(--selaras-resolved-text-default)] ring-1 ring-inset ring-[var(--selaras-resolved-border-default)] hover:ring-[var(--selaras-resolved-border-hover)] hover:bg-[var(--selaras-resolved-surface-elevated)]",
|
|
454
|
-
datePickerInvalid.value ? "ring-[var(--_selaras-color-fill)] hover:ring-[var(--_selaras-color-fill)]" : void 0
|
|
455
|
-
// Room for the clear button, which sits absolutely positioned on top of
|
|
456
|
-
// this same end edge - without it, a long formatted date can run under it.
|
|
457
|
-
props.clearable && hasValue.value ? "pe-8" : void 0
|
|
470
|
+
datePickerInvalid.value ? "ring-[var(--_selaras-color-fill)] hover:ring-[var(--_selaras-color-fill)]" : void 0
|
|
458
471
|
].filter(Boolean).join(" "),
|
|
459
472
|
// base is justify-start (text left-aligned, not centered) so the button
|
|
460
473
|
// reads naturally for a short date string - without its own auto margin,
|
|
@@ -497,7 +510,7 @@ const buttonTriggerUi = computed(() => ({
|
|
|
497
510
|
@update:model-value="(value) => updateModelValue(value)"
|
|
498
511
|
>
|
|
499
512
|
<DateRangePickerAnchor as-child>
|
|
500
|
-
<div v-if="triggerMode === 'field'" data-selaras-field-segmented :data-selaras-color="fieldColor" :data-selaras-field-filled="hasValue ? '' : void 0" :data-selaras-field-active="open ? '' : void 0" :aria-invalid="datePickerInvalid || void 0" :aria-describedby="describedBy" v-bind="fieldProps" :aria-labelledby="field?.labelId">
|
|
513
|
+
<div v-if="triggerMode === 'field'" ref="fieldElement" data-selaras-field-segmented :data-selaras-color="fieldColor" :data-selaras-field-filled="hasValue ? '' : void 0" :data-selaras-field-active="open ? '' : void 0" :aria-invalid="datePickerInvalid || void 0" :aria-describedby="describedBy" v-bind="fieldProps" :aria-labelledby="field?.labelId">
|
|
501
514
|
<DateRangePickerField v-slot="{ segments }" :aria-labelledby="field?.labelId" :aria-describedby="describedBy" :aria-invalid="datePickerInvalid || void 0">
|
|
502
515
|
<template v-for="segment in segments.start" :key="`start-${segment.part}`">
|
|
503
516
|
<DateRangePickerInput as="span" type="start" :part="segment.part" v-bind="segmentProps">
|
|
@@ -512,22 +525,13 @@ const buttonTriggerUi = computed(() => ({
|
|
|
512
525
|
</template>
|
|
513
526
|
</DateRangePickerField>
|
|
514
527
|
<div :class="applyClassPrefix('ms-auto flex shrink-0 items-center gap-1')">
|
|
515
|
-
<
|
|
516
|
-
v-if="
|
|
517
|
-
|
|
518
|
-
:color="color"
|
|
519
|
-
:size="iconButtonSize"
|
|
520
|
-
:aria-label="messages.clear"
|
|
521
|
-
@click="clear"
|
|
522
|
-
>
|
|
523
|
-
<template #icon="{ class: iconClass }">
|
|
524
|
-
<slot name="clear-icon">
|
|
525
|
-
<Icon :name="icons.close" :class="iconClass" />
|
|
526
|
-
</slot>
|
|
528
|
+
<FieldClearButton v-if="showClear" :size="effectiveSize" v-bind="clearProps" @click.stop="clear">
|
|
529
|
+
<template v-if="$slots['clear-icon']" #default>
|
|
530
|
+
<slot name="clear-icon" />
|
|
527
531
|
</template>
|
|
528
|
-
</
|
|
532
|
+
</FieldClearButton>
|
|
529
533
|
<DateRangePickerTrigger as-child>
|
|
530
|
-
<Button variant="text" :color="color" :size="iconButtonSize" :aria-label="messages.dateRangePicker">
|
|
534
|
+
<Button variant="text" :color="color" :size="iconButtonSize" :ui="{ leadingIcon: triggerIconProps }" :aria-label="messages.dateRangePicker">
|
|
531
535
|
<template #icon="{ class: iconClass }">
|
|
532
536
|
<slot name="trigger-icon">
|
|
533
537
|
<Icon :name="icons.calendar" :class="iconClass" />
|
|
@@ -542,6 +546,7 @@ const buttonTriggerUi = computed(() => ({
|
|
|
542
546
|
<DateRangePickerTrigger as-child>
|
|
543
547
|
<Button
|
|
544
548
|
:id="datePickerId"
|
|
549
|
+
ref="buttonTrigger"
|
|
545
550
|
variant="text"
|
|
546
551
|
:color="color"
|
|
547
552
|
:size="effectiveSize"
|
|
@@ -550,29 +555,19 @@ const buttonTriggerUi = computed(() => ({
|
|
|
550
555
|
:aria-labelledby="field?.labelId"
|
|
551
556
|
:ui="buttonTriggerUi"
|
|
552
557
|
>
|
|
553
|
-
{{ hasValue ? formattedValue : field?.floatingLabel.value ? "" : messages.pickDate }}
|
|
554
|
-
<template
|
|
558
|
+
<span :class="applyClassPrefix('min-w-0 flex-1 truncate text-start')" :style="buttonLabelStyle">{{ hasValue ? formattedValue : field?.floatingLabel.value ? "" : messages.pickDate }}</span>
|
|
559
|
+
<template #trailing-icon="{ class: iconClass }">
|
|
555
560
|
<slot name="trigger-icon">
|
|
556
561
|
<Icon :name="icons.calendar" :class="iconClass" />
|
|
557
562
|
</slot>
|
|
558
563
|
</template>
|
|
559
564
|
</Button>
|
|
560
565
|
</DateRangePickerTrigger>
|
|
561
|
-
<
|
|
562
|
-
v-if="
|
|
563
|
-
|
|
564
|
-
:color="color"
|
|
565
|
-
:size="iconButtonSize"
|
|
566
|
-
:aria-label="messages.clear"
|
|
567
|
-
:class="applyClassPrefix('absolute end-1 top-1/2 -translate-y-1/2')"
|
|
568
|
-
@click.stop="clear"
|
|
569
|
-
>
|
|
570
|
-
<template #icon="{ class: iconClass }">
|
|
571
|
-
<slot name="clear-icon">
|
|
572
|
-
<Icon :name="icons.close" :class="iconClass" />
|
|
573
|
-
</slot>
|
|
566
|
+
<FieldClearButton v-if="showClear" :size="effectiveSize" v-bind="mergeProps(clearProps, buttonClearProps)" @click.stop="clear">
|
|
567
|
+
<template v-if="$slots['clear-icon']" #default>
|
|
568
|
+
<slot name="clear-icon" />
|
|
574
569
|
</template>
|
|
575
|
-
</
|
|
570
|
+
</FieldClearButton>
|
|
576
571
|
</div>
|
|
577
572
|
</DateRangePickerAnchor>
|
|
578
573
|
|
|
@@ -616,7 +611,7 @@ const buttonTriggerUi = computed(() => ({
|
|
|
616
611
|
|
|
617
612
|
<PopoverRoot v-else-if="timeOnly" :open="open" :data-selaras-color="fieldColor" @update:open="onUpdateOpen">
|
|
618
613
|
<PopoverAnchor as-child>
|
|
619
|
-
<div v-if="triggerMode === 'field'" data-selaras-field-segmented :data-selaras-color="fieldColor" :data-selaras-field-filled="hasValue ? '' : void 0" :data-selaras-field-active="open ? '' : void 0" :aria-invalid="datePickerInvalid || void 0" :aria-describedby="describedBy" v-bind="fieldProps" :aria-labelledby="field?.labelId">
|
|
614
|
+
<div v-if="triggerMode === 'field'" ref="fieldElement" data-selaras-field-segmented :data-selaras-color="fieldColor" :data-selaras-field-filled="hasValue ? '' : void 0" :data-selaras-field-active="open ? '' : void 0" :aria-invalid="datePickerInvalid || void 0" :aria-describedby="describedBy" v-bind="fieldProps" :aria-labelledby="field?.labelId">
|
|
620
615
|
<TimeFieldRoot
|
|
621
616
|
:id="datePickerId"
|
|
622
617
|
v-slot="{ segments }"
|
|
@@ -640,22 +635,13 @@ const buttonTriggerUi = computed(() => ({
|
|
|
640
635
|
</template>
|
|
641
636
|
</TimeFieldRoot>
|
|
642
637
|
<div :class="applyClassPrefix('ms-auto flex shrink-0 items-center gap-1')">
|
|
643
|
-
<
|
|
644
|
-
v-if="
|
|
645
|
-
|
|
646
|
-
:color="color"
|
|
647
|
-
:size="iconButtonSize"
|
|
648
|
-
:aria-label="messages.clear"
|
|
649
|
-
@click="clear"
|
|
650
|
-
>
|
|
651
|
-
<template #icon="{ class: iconClass }">
|
|
652
|
-
<slot name="clear-icon">
|
|
653
|
-
<Icon :name="icons.close" :class="iconClass" />
|
|
654
|
-
</slot>
|
|
638
|
+
<FieldClearButton v-if="showClear" :size="effectiveSize" v-bind="clearProps" @click.stop="clear">
|
|
639
|
+
<template v-if="$slots['clear-icon']" #default>
|
|
640
|
+
<slot name="clear-icon" />
|
|
655
641
|
</template>
|
|
656
|
-
</
|
|
642
|
+
</FieldClearButton>
|
|
657
643
|
<PopoverTrigger as-child>
|
|
658
|
-
<Button variant="text" :color="color" :size="iconButtonSize" :aria-label="messages.timePicker">
|
|
644
|
+
<Button variant="text" :color="color" :size="iconButtonSize" :ui="{ leadingIcon: triggerIconProps }" :aria-label="messages.timePicker">
|
|
659
645
|
<template #icon="{ class: iconClass }">
|
|
660
646
|
<slot name="trigger-icon">
|
|
661
647
|
<Icon :name="icons.clock" :class="iconClass" />
|
|
@@ -670,6 +656,7 @@ const buttonTriggerUi = computed(() => ({
|
|
|
670
656
|
<PopoverTrigger as-child>
|
|
671
657
|
<Button
|
|
672
658
|
:id="datePickerId"
|
|
659
|
+
ref="buttonTrigger"
|
|
673
660
|
variant="text"
|
|
674
661
|
:color="color"
|
|
675
662
|
:size="effectiveSize"
|
|
@@ -678,29 +665,19 @@ const buttonTriggerUi = computed(() => ({
|
|
|
678
665
|
:aria-labelledby="field?.labelId"
|
|
679
666
|
:ui="buttonTriggerUi"
|
|
680
667
|
>
|
|
681
|
-
{{ hasValue ? formattedTimeValue : field?.floatingLabel.value ? "" : messages.pickTime }}
|
|
682
|
-
<template
|
|
668
|
+
<span :class="applyClassPrefix('min-w-0 flex-1 truncate text-start')" :style="buttonLabelStyle">{{ hasValue ? formattedTimeValue : field?.floatingLabel.value ? "" : messages.pickTime }}</span>
|
|
669
|
+
<template #trailing-icon="{ class: iconClass }">
|
|
683
670
|
<slot name="trigger-icon">
|
|
684
671
|
<Icon :name="icons.clock" :class="iconClass" />
|
|
685
672
|
</slot>
|
|
686
673
|
</template>
|
|
687
674
|
</Button>
|
|
688
675
|
</PopoverTrigger>
|
|
689
|
-
<
|
|
690
|
-
v-if="
|
|
691
|
-
|
|
692
|
-
:color="color"
|
|
693
|
-
:size="iconButtonSize"
|
|
694
|
-
:aria-label="messages.clear"
|
|
695
|
-
:class="applyClassPrefix('absolute end-1 top-1/2 -translate-y-1/2')"
|
|
696
|
-
@click.stop="clear"
|
|
697
|
-
>
|
|
698
|
-
<template #icon="{ class: iconClass }">
|
|
699
|
-
<slot name="clear-icon">
|
|
700
|
-
<Icon :name="icons.close" :class="iconClass" />
|
|
701
|
-
</slot>
|
|
676
|
+
<FieldClearButton v-if="showClear" :size="effectiveSize" v-bind="mergeProps(clearProps, buttonClearProps)" @click.stop="clear">
|
|
677
|
+
<template v-if="$slots['clear-icon']" #default>
|
|
678
|
+
<slot name="clear-icon" />
|
|
702
679
|
</template>
|
|
703
|
-
</
|
|
680
|
+
</FieldClearButton>
|
|
704
681
|
</div>
|
|
705
682
|
</PopoverAnchor>
|
|
706
683
|
|
|
@@ -760,7 +737,7 @@ const buttonTriggerUi = computed(() => ({
|
|
|
760
737
|
@update:model-value="(value) => updateModelValue(normalizeForGranularity(value))"
|
|
761
738
|
>
|
|
762
739
|
<DatePickerAnchor as-child>
|
|
763
|
-
<div v-if="triggerMode === 'field'" data-selaras-field-segmented :data-selaras-color="fieldColor" :data-selaras-field-filled="hasValue ? '' : void 0" :data-selaras-field-active="open ? '' : void 0" :aria-invalid="datePickerInvalid || void 0" :aria-describedby="describedBy" v-bind="fieldProps" :aria-labelledby="field?.labelId">
|
|
740
|
+
<div v-if="triggerMode === 'field'" ref="fieldElement" data-selaras-field-segmented :data-selaras-color="fieldColor" :data-selaras-field-filled="hasValue ? '' : void 0" :data-selaras-field-active="open ? '' : void 0" :aria-invalid="datePickerInvalid || void 0" :aria-describedby="describedBy" v-bind="fieldProps" :aria-labelledby="field?.labelId">
|
|
764
741
|
<DatePickerField v-slot="{ segments }" :aria-labelledby="field?.labelId" :aria-describedby="describedBy" :aria-invalid="datePickerInvalid || void 0">
|
|
765
742
|
<template v-for="(segment, index) in visibleSegments(segments)" :key="`${segment.part}-${index}`">
|
|
766
743
|
<DatePickerInput as="span" :part="segment.part" v-bind="segmentProps">
|
|
@@ -769,22 +746,13 @@ const buttonTriggerUi = computed(() => ({
|
|
|
769
746
|
</template>
|
|
770
747
|
</DatePickerField>
|
|
771
748
|
<div :class="applyClassPrefix('ms-auto flex shrink-0 items-center gap-1')">
|
|
772
|
-
<
|
|
773
|
-
v-if="
|
|
774
|
-
|
|
775
|
-
:color="color"
|
|
776
|
-
:size="iconButtonSize"
|
|
777
|
-
:aria-label="messages.clear"
|
|
778
|
-
@click="clear"
|
|
779
|
-
>
|
|
780
|
-
<template #icon="{ class: iconClass }">
|
|
781
|
-
<slot name="clear-icon">
|
|
782
|
-
<Icon :name="icons.close" :class="iconClass" />
|
|
783
|
-
</slot>
|
|
749
|
+
<FieldClearButton v-if="showClear" :size="effectiveSize" v-bind="clearProps" @click.stop="clear">
|
|
750
|
+
<template v-if="$slots['clear-icon']" #default>
|
|
751
|
+
<slot name="clear-icon" />
|
|
784
752
|
</template>
|
|
785
|
-
</
|
|
753
|
+
</FieldClearButton>
|
|
786
754
|
<DatePickerTrigger as-child>
|
|
787
|
-
<Button variant="text" :color="color" :size="iconButtonSize" :aria-label="messages.datePicker">
|
|
755
|
+
<Button variant="text" :color="color" :size="iconButtonSize" :ui="{ leadingIcon: triggerIconProps }" :aria-label="messages.datePicker">
|
|
788
756
|
<template #icon="{ class: iconClass }">
|
|
789
757
|
<slot name="trigger-icon">
|
|
790
758
|
<Icon :name="icons.calendar" :class="iconClass" />
|
|
@@ -799,6 +767,7 @@ const buttonTriggerUi = computed(() => ({
|
|
|
799
767
|
<DatePickerTrigger as-child>
|
|
800
768
|
<Button
|
|
801
769
|
:id="datePickerId"
|
|
770
|
+
ref="buttonTrigger"
|
|
802
771
|
variant="text"
|
|
803
772
|
:color="color"
|
|
804
773
|
:size="effectiveSize"
|
|
@@ -807,29 +776,19 @@ const buttonTriggerUi = computed(() => ({
|
|
|
807
776
|
:aria-labelledby="field?.labelId"
|
|
808
777
|
:ui="buttonTriggerUi"
|
|
809
778
|
>
|
|
810
|
-
{{ hasValue ? formattedValue : field?.floatingLabel.value ? "" : messages.pickDate }}
|
|
811
|
-
<template
|
|
779
|
+
<span :class="applyClassPrefix('min-w-0 flex-1 truncate text-start')" :style="buttonLabelStyle">{{ hasValue ? formattedValue : field?.floatingLabel.value ? "" : messages.pickDate }}</span>
|
|
780
|
+
<template #trailing-icon="{ class: iconClass }">
|
|
812
781
|
<slot name="trigger-icon">
|
|
813
782
|
<Icon :name="icons.calendar" :class="iconClass" />
|
|
814
783
|
</slot>
|
|
815
784
|
</template>
|
|
816
785
|
</Button>
|
|
817
786
|
</DatePickerTrigger>
|
|
818
|
-
<
|
|
819
|
-
v-if="
|
|
820
|
-
|
|
821
|
-
:color="color"
|
|
822
|
-
:size="iconButtonSize"
|
|
823
|
-
:aria-label="messages.clear"
|
|
824
|
-
:class="applyClassPrefix('absolute end-1 top-1/2 -translate-y-1/2')"
|
|
825
|
-
@click.stop="clear"
|
|
826
|
-
>
|
|
827
|
-
<template #icon="{ class: iconClass }">
|
|
828
|
-
<slot name="clear-icon">
|
|
829
|
-
<Icon :name="icons.close" :class="iconClass" />
|
|
830
|
-
</slot>
|
|
787
|
+
<FieldClearButton v-if="showClear" :size="effectiveSize" v-bind="mergeProps(clearProps, buttonClearProps)" @click.stop="clear">
|
|
788
|
+
<template v-if="$slots['clear-icon']" #default>
|
|
789
|
+
<slot name="clear-icon" />
|
|
831
790
|
</template>
|
|
832
|
-
</
|
|
791
|
+
</FieldClearButton>
|
|
833
792
|
</div>
|
|
834
793
|
</DatePickerAnchor>
|
|
835
794
|
|