minerva-design 1.0.0 → 1.0.2

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.
Files changed (138) hide show
  1. package/CHANGELOG.md +12 -0
  2. package/custom-elements.json +663 -0
  3. package/dist/angular/fesm2022/minerva-angular.mjs +1163 -34
  4. package/dist/angular/fesm2022/minerva-angular.mjs.map +1 -1
  5. package/dist/angular/types/minerva-angular.d.ts +237 -1
  6. package/dist/core/calendar-date.d.cts +5 -0
  7. package/dist/core/calendar-date.d.ts +5 -0
  8. package/dist/core/contracts.cjs +1 -1
  9. package/dist/core/contracts.cjs.map +1 -1
  10. package/dist/core/contracts.js +1 -1
  11. package/dist/core/contracts.js.map +1 -1
  12. package/dist/core/index.cjs +6 -6
  13. package/dist/core/index.cjs.map +1 -1
  14. package/dist/core/index.js +671 -630
  15. package/dist/core/index.js.map +1 -1
  16. package/dist/core/styling-hooks/components/date-picker.d.cts +45 -0
  17. package/dist/core/styling-hooks/components/date-picker.d.ts +45 -0
  18. package/dist/core/styling-hooks/manifest.d.cts +44 -0
  19. package/dist/core/styling-hooks/manifest.d.ts +44 -0
  20. package/dist/core/styling-hooks.cjs +1 -1
  21. package/dist/core/styling-hooks.cjs.map +1 -1
  22. package/dist/core/styling-hooks.js +62 -0
  23. package/dist/core/styling-hooks.js.map +1 -1
  24. package/dist/native/components/Calendar/Calendar.cjs +1 -1
  25. package/dist/native/components/Calendar/Calendar.cjs.map +1 -1
  26. package/dist/native/components/Calendar/Calendar.d.cts +2 -0
  27. package/dist/native/components/Calendar/Calendar.d.ts +2 -0
  28. package/dist/native/components/Calendar/Calendar.js +115 -112
  29. package/dist/native/components/Calendar/Calendar.js.map +1 -1
  30. package/dist/native/components/Checkbox/Checkbox.cjs +1 -1
  31. package/dist/native/components/Checkbox/Checkbox.cjs.map +1 -1
  32. package/dist/native/components/Checkbox/Checkbox.js +8 -8
  33. package/dist/native/components/Checkbox/CheckboxGroup.cjs +1 -1
  34. package/dist/native/components/Checkbox/CheckboxGroup.cjs.map +1 -1
  35. package/dist/native/components/Checkbox/CheckboxGroup.js +6 -6
  36. package/dist/native/components/DatePicker/DatePicker.cjs +2 -0
  37. package/dist/native/components/DatePicker/DatePicker.cjs.map +1 -0
  38. package/dist/native/components/DatePicker/DatePicker.d.cts +40 -0
  39. package/dist/native/components/DatePicker/DatePicker.d.ts +40 -0
  40. package/dist/native/components/DatePicker/DatePicker.js +110 -0
  41. package/dist/native/components/DatePicker/DatePicker.js.map +1 -0
  42. package/dist/native/components/DatePicker/index.cjs +1 -0
  43. package/dist/native/components/DatePicker/index.d.cts +2 -0
  44. package/dist/native/components/DatePicker/index.d.ts +2 -0
  45. package/dist/native/components/DatePicker/index.js +2 -0
  46. package/dist/native/components/Radio/RadioGroup.cjs +1 -1
  47. package/dist/native/components/Radio/RadioGroup.cjs.map +1 -1
  48. package/dist/native/components/Radio/RadioGroup.js +9 -9
  49. package/dist/native/components/Switch/Switch.cjs +1 -1
  50. package/dist/native/components/Switch/Switch.cjs.map +1 -1
  51. package/dist/native/components/Switch/Switch.js +23 -23
  52. package/dist/native/components/Switch/Switch.js.map +1 -1
  53. package/dist/native/index.cjs +1 -1
  54. package/dist/native/index.d.cts +1 -0
  55. package/dist/native/index.d.ts +1 -0
  56. package/dist/native/index.js +70 -68
  57. package/dist/native/source/components/Calendar/Calendar.tsx +14 -6
  58. package/dist/native/source/components/DatePicker/DatePicker.tsx +201 -0
  59. package/dist/native/source/components/DatePicker/index.ts +2 -0
  60. package/dist/native/source/index.ts +1 -0
  61. package/dist/native/source/manifest.ts +6 -0
  62. package/dist/react/components/DatePicker/DatePicker.cjs +2 -0
  63. package/dist/react/components/DatePicker/DatePicker.cjs.map +1 -0
  64. package/dist/react/components/DatePicker/DatePicker.d.cts +13 -0
  65. package/dist/react/components/DatePicker/DatePicker.d.ts +13 -0
  66. package/dist/react/components/DatePicker/DatePicker.js +315 -0
  67. package/dist/react/components/DatePicker/DatePicker.js.map +1 -0
  68. package/dist/react/components/DatePicker/datePicker.module.scss.cjs +2 -0
  69. package/dist/react/components/DatePicker/datePicker.module.scss.cjs.map +1 -0
  70. package/dist/react/components/DatePicker/datePicker.module.scss.js +23 -0
  71. package/dist/react/components/DatePicker/datePicker.module.scss.js.map +1 -0
  72. package/dist/react/components/DatePicker/index.cjs +1 -0
  73. package/dist/react/components/DatePicker/index.d.cts +5 -0
  74. package/dist/react/components/DatePicker/index.d.ts +5 -0
  75. package/dist/react/components/DatePicker/index.js +3 -0
  76. package/dist/react/components/DatePicker/types.d.cts +97 -0
  77. package/dist/react/components/DatePicker/types.d.ts +97 -0
  78. package/dist/react/components/Tooltip/Tooltip.cjs +1 -1
  79. package/dist/react/components/Tooltip/Tooltip.cjs.map +1 -1
  80. package/dist/react/components/Tooltip/Tooltip.js +5 -5
  81. package/dist/react/components/Tooltip/Tooltip.js.map +1 -1
  82. package/dist/react/components/index.cjs +1 -1
  83. package/dist/react/components/index.d.cts +1 -0
  84. package/dist/react/components/index.d.ts +1 -0
  85. package/dist/react/components/index.js +3 -1
  86. package/dist/react/index.cjs +1 -1
  87. package/dist/react/index.js +7 -6
  88. package/dist/react/style.css +1 -0
  89. package/dist/react/styles/date-picker.css +7 -0
  90. package/dist/taro/date-picker.d.ts +20 -0
  91. package/dist/taro/index.d.ts +1 -0
  92. package/dist/taro/index.js +1155 -990
  93. package/dist/uni/DatePicker.vue +225 -0
  94. package/dist/uni/DatePicker.vue.d.ts +36 -0
  95. package/dist/uni/MonthCalendar.vue +2 -0
  96. package/dist/uni/MonthCalendar.vue.d.ts +2 -0
  97. package/dist/uni/index.d.ts +1 -0
  98. package/dist/uni/index.js +1 -0
  99. package/dist/uni/manifest.d.ts +7 -0
  100. package/dist/uni/manifest.js +8 -0
  101. package/dist/vue/components/DatePicker/DatePicker.vue.d.ts +36 -0
  102. package/dist/vue/components/DatePicker/DatePicker.vue.js +7 -0
  103. package/dist/vue/components/DatePicker/DatePicker.vue.js.map +1 -0
  104. package/dist/vue/components/DatePicker/DatePicker.vue_vue_type_script_setup_true_lang.js +380 -0
  105. package/dist/vue/components/DatePicker/DatePicker.vue_vue_type_script_setup_true_lang.js.map +1 -0
  106. package/dist/vue/components/DatePicker/index.d.ts +2 -0
  107. package/dist/vue/components/DatePicker/index.js +2 -0
  108. package/dist/vue/components/DatePicker/types.d.ts +26 -0
  109. package/dist/vue/components/MonthCalendar/MonthCalendar.vue.d.ts +1 -1
  110. package/dist/vue/global.d.ts +108 -0
  111. package/dist/vue/groups/forms-pickers.d.ts +1 -0
  112. package/dist/vue/groups/forms-pickers.js +5 -2
  113. package/dist/vue/groups/forms-pickers.js.map +1 -1
  114. package/dist/vue/index.js +95 -94
  115. package/dist/weapp/controls.js +259 -76
  116. package/dist/weapp/date-picker/index.js +1 -0
  117. package/dist/weapp/date-picker/index.json +1 -0
  118. package/dist/weapp/date-picker/index.wxml +1 -0
  119. package/dist/weapp/date-picker/index.wxss +1 -0
  120. package/dist/weapp/types.d.ts +19 -0
  121. package/dist/web-components/cdn/minerva.js +461 -335
  122. package/dist/web-components/cdn/minerva.js.map +1 -1
  123. package/dist/web-components/components/date-picker/date-picker.d.ts +110 -0
  124. package/dist/web-components/components/date-picker/date-picker.js +378 -0
  125. package/dist/web-components/components/date-picker/date-picker.js.map +1 -0
  126. package/dist/web-components/elements/date-picker.d.ts +1 -0
  127. package/dist/web-components/elements/date-picker.js +8 -0
  128. package/dist/web-components/elements/date-picker.js.map +1 -0
  129. package/dist/web-components/html-custom-data.json +85 -0
  130. package/dist/web-components/index.d.ts +1 -0
  131. package/dist/web-components/index.js +8 -6
  132. package/dist/web-components/styles/DatePicker/datePicker.css.js +6 -0
  133. package/dist/web-components/styles/DatePicker/datePicker.css.js.map +1 -0
  134. package/dist/web-components/types/react.d.ts +12 -0
  135. package/dist/web-components/types/solid.d.ts +9 -0
  136. package/dist/web-components/types/svelte.d.ts +9 -0
  137. package/dist/web-components/types/vue.d.ts +10 -0
  138. package/package.json +9 -1
@@ -0,0 +1,225 @@
1
+ <script setup lang="ts">
2
+ import { computed, ref, watch, provide, getCurrentInstance } from "vue";
3
+ import { dayKey, monthStart, parseDayKey } from "../core/index.js";
4
+ import Input from "./Input.vue";
5
+ import MonthCalendar from "./MonthCalendar.vue";
6
+ import PopoverContent from "./PopoverContent.vue";
7
+ import type { MiniPopoverContext } from "./popover-context.js";
8
+ import { inheritForm } from "./form-context.js";
9
+ import { useI18n } from "./i18n.js";
10
+ import { useNativeId } from "./native-id.js";
11
+ const raw = withDefaults(
12
+ defineProps<{
13
+ value?: string | null;
14
+ modelValue?: string | null;
15
+ defaultValue?: string;
16
+ minDate?: string;
17
+ maxDate?: string;
18
+ disabled?: boolean;
19
+ readOnly?: boolean;
20
+ required?: boolean;
21
+ invalid?: boolean;
22
+ clearable?: boolean;
23
+ placeholder?: string;
24
+ label?: string;
25
+ name?: string;
26
+ id?: string;
27
+ ariaLabel?: string;
28
+ ariaLabelledby?: string;
29
+ ariaDescribedby?: string;
30
+ locale?: string;
31
+ size?: "small" | "medium" | "large";
32
+ }>(),
33
+ { clearable: true, name: "date-picker", size: "medium" },
34
+ );
35
+ const props = inheritForm(raw),
36
+ { t } = useI18n();
37
+ const emit = defineEmits<{
38
+ change: [value: string];
39
+ "update:modelValue": [value: string];
40
+ openChange: [open: boolean];
41
+ }>();
42
+ const local = ref(props.defaultValue ?? ""),
43
+ draft = ref<string | null>(null),
44
+ open = ref(false);
45
+ const current = computed(() =>
46
+ props.modelValue !== undefined
47
+ ? (props.modelValue ?? "")
48
+ : props.value !== undefined
49
+ ? (props.value ?? "")
50
+ : local.value,
51
+ );
52
+ const month = ref(monthStart(parseDayKey(current.value) ?? new Date()));
53
+ const blocked = computed(() => props.disabled || props.readOnly);
54
+ const field = ref<any>(),
55
+ fieldId = `mn-date-${useNativeId()}`;
56
+ const instance = getCurrentInstance();
57
+ let touching = false;
58
+ function setOpen(next: boolean) {
59
+ if ((next && blocked.value) || next === open.value) return;
60
+ open.value = next;
61
+ emit("openChange", next);
62
+ if (next) month.value = monthStart(parseDayKey(current.value) ?? new Date());
63
+ }
64
+ watch(blocked, (value) => {
65
+ if (value) setOpen(false);
66
+ });
67
+ watch(
68
+ () => [props.value, props.modelValue],
69
+ () => {
70
+ draft.value = null;
71
+ },
72
+ );
73
+ const allowed = (key: string) =>
74
+ (!props.minDate || key >= props.minDate) &&
75
+ (!props.maxDate || key <= props.maxDate);
76
+ function commit(next: string) {
77
+ if (blocked.value) return;
78
+ if (props.value === undefined && props.modelValue === undefined)
79
+ local.value = next;
80
+ emit("change", next);
81
+ emit("update:modelValue", next);
82
+ }
83
+ function input(text: string) {
84
+ if (blocked.value) return;
85
+ draft.value = text;
86
+ if (!text) commit("");
87
+ else {
88
+ const parsed = parseDayKey(text, true);
89
+ if (parsed && allowed(dayKey(parsed))) {
90
+ commit(dayKey(parsed));
91
+ month.value = monthStart(parsed);
92
+ }
93
+ }
94
+ }
95
+ function blur() {
96
+ if (touching) {
97
+ touching = false;
98
+ return;
99
+ }
100
+ if (blocked.value || draft.value === null) return;
101
+ const parsed = parseDayKey(draft.value.trim(), false);
102
+ if (!draft.value.trim()) {
103
+ if (current.value) commit("");
104
+ } else if (parsed) {
105
+ const key = dayKey(parsed);
106
+ if (allowed(key) && key !== current.value) {
107
+ commit(key);
108
+ month.value = monthStart(parsed);
109
+ }
110
+ }
111
+ draft.value = null;
112
+ }
113
+ function choose(key: string) {
114
+ touching = false;
115
+ if (blocked.value || !allowed(key)) return;
116
+ draft.value = null;
117
+ commit(key);
118
+ setOpen(false);
119
+ }
120
+ function clear() {
121
+ touching = false;
122
+ draft.value = null;
123
+ commit("");
124
+ }
125
+ provide<MiniPopoverContext>("minerva:popover", {
126
+ open: computed(() => open.value && !blocked.value),
127
+ disabled: blocked,
128
+ placement: computed(() => "bottom"),
129
+ modal: computed(() => false),
130
+ setOpen,
131
+ trigger: field,
132
+ anchor: ref(),
133
+ anchorId: ref(""),
134
+ triggerId: fieldId,
135
+ measureTrigger: (callback) => {
136
+ uni
137
+ .createSelectorQuery?.()
138
+ .in(instance?.proxy)
139
+ .select(`#${fieldId}`)
140
+ .boundingClientRect((rect: any) => {
141
+ if (rect) callback(rect);
142
+ })
143
+ .exec();
144
+ },
145
+ });
146
+ </script>
147
+ <template>
148
+ <view
149
+ :id="fieldId"
150
+ class="mn-uni-date-picker"
151
+ :data-state="open ? 'open' : 'closed'"
152
+ >
153
+ <text v-if="label">{{ label }}</text>
154
+ <Input
155
+ ref="field"
156
+ :id="props.id"
157
+ :value="draft ?? current"
158
+ :name="name"
159
+ :size="size"
160
+ :placeholder="placeholder ?? t('datePicker.placeholder')"
161
+ :aria-label="label ?? props.ariaLabel ?? t('datePicker.label')"
162
+ :aria-labelledby="props.ariaLabelledby"
163
+ :aria-describedby="props.ariaDescribedby"
164
+ :disabled="props.disabled"
165
+ :read-only="props.readOnly"
166
+ :required="props.required"
167
+ :invalid="props.invalid"
168
+ @change="input"
169
+ @blur="blur"
170
+ @confirm="
171
+ blur();
172
+ setOpen(false);
173
+ "
174
+ @click="setOpen(!open)"
175
+ @keydown="
176
+ if ($event.key === 'Escape') setOpen(false);
177
+ else if ($event.key === 'ArrowDown') setOpen(true);
178
+ "
179
+ >
180
+ <template #suffix
181
+ ><button
182
+ v-if="clearable && current && !blocked"
183
+ class="mn-close"
184
+ :aria-label="t('datePicker.clear')"
185
+ @touchstart="touching = true"
186
+ @touchcancel="touching = false"
187
+ @mousedown.prevent
188
+ @tap.stop="clear"
189
+ >
190
+ ×
191
+ </button></template
192
+ >
193
+ </Input>
194
+ <PopoverContent
195
+ align="start"
196
+ :aria-label="label ?? props.ariaLabel ?? t('datePicker.label')"
197
+ @open-auto-focus="$event.preventDefault()"
198
+ >
199
+ <view
200
+ @touchstart="touching = true"
201
+ @touchcancel="touching = false"
202
+ @mousedown.prevent
203
+ >
204
+ <MonthCalendar
205
+ :month="month"
206
+ :value="current"
207
+ :min="minDate"
208
+ :max="maxDate"
209
+ :locale="locale"
210
+ :size="size"
211
+ :show-selected-day-events="false"
212
+ @month-change="month = $event"
213
+ @select="choose"
214
+ />
215
+ <button
216
+ class="mn-button mn-variant-ghost"
217
+ :disabled="!allowed(dayKey(new Date()))"
218
+ @tap="choose(dayKey(new Date()))"
219
+ >
220
+ {{ t("datePicker.today") }}
221
+ </button>
222
+ </view>
223
+ </PopoverContent>
224
+ </view>
225
+ </template>
@@ -0,0 +1,36 @@
1
+ type __VLS_Props = {
2
+ value?: string | null;
3
+ modelValue?: string | null;
4
+ defaultValue?: string;
5
+ minDate?: string;
6
+ maxDate?: string;
7
+ disabled?: boolean;
8
+ readOnly?: boolean;
9
+ required?: boolean;
10
+ invalid?: boolean;
11
+ clearable?: boolean;
12
+ placeholder?: string;
13
+ label?: string;
14
+ name?: string;
15
+ id?: string;
16
+ ariaLabel?: string;
17
+ ariaLabelledby?: string;
18
+ ariaDescribedby?: string;
19
+ locale?: string;
20
+ size?: "small" | "medium" | "large";
21
+ };
22
+ declare const __VLS_export: import("vue").DefineComponent<__VLS_Props, {}, {}, {}, {}, import("vue").ComponentOptionsMixin, import("vue").ComponentOptionsMixin, {
23
+ change: (value: string) => any;
24
+ "update:modelValue": (value: string) => any;
25
+ openChange: (open: boolean) => any;
26
+ }, string, import("vue").PublicProps, Readonly<__VLS_Props> & Readonly<{
27
+ onChange?: ((value: string) => any) | undefined;
28
+ "onUpdate:modelValue"?: ((value: string) => any) | undefined;
29
+ onOpenChange?: ((open: boolean) => any) | undefined;
30
+ }>, {
31
+ size: "small" | "medium" | "large";
32
+ name: string;
33
+ clearable: boolean;
34
+ }, {}, {}, {}, string, import("vue").ComponentProvideOptions, false, {}, any>;
35
+ declare const _default: typeof __VLS_export;
36
+ export default _default;
@@ -49,6 +49,7 @@ const props = withDefaults(
49
49
  );
50
50
  const emit = defineEmits<{
51
51
  change: [day: string];
52
+ select: [day: string];
52
53
  "update:modelValue": [day: string];
53
54
  monthChange: [date: Date];
54
55
  "update:month": [date: Date];
@@ -157,6 +158,7 @@ function goTo(date: Date) {
157
158
  function choose(date: Date) {
158
159
  const day = dayKey(date);
159
160
  if (blocked(day)) return;
161
+ emit("select", day);
160
162
  const changed = day !== selected.value;
161
163
  if (props.value === undefined && props.modelValue === undefined)
162
164
  localValue.value = day;
@@ -43,12 +43,14 @@ type __VLS_Slots = {} & {
43
43
  event?: (props: typeof __VLS_6) => any;
44
44
  };
45
45
  declare const __VLS_base: import("vue").DefineComponent<__VLS_Props, {}, {}, {}, {}, import("vue").ComponentOptionsMixin, import("vue").ComponentOptionsMixin, {
46
+ select: (day: string) => any;
46
47
  change: (day: string) => any;
47
48
  "update:modelValue": (day: string) => any;
48
49
  monthChange: (date: Date) => any;
49
50
  "update:month": (date: Date) => any;
50
51
  eventClick: (event: CalendarEvent) => any;
51
52
  }, string, import("vue").PublicProps, Readonly<__VLS_Props> & Readonly<{
53
+ onSelect?: ((day: string) => any) | undefined;
52
54
  onChange?: ((day: string) => any) | undefined;
53
55
  "onUpdate:modelValue"?: ((day: string) => any) | undefined;
54
56
  onMonthChange?: ((date: Date) => any) | undefined;
@@ -123,3 +123,4 @@ export { default as ToastProvider } from "./ToastProvider.vue.js";
123
123
  export { default as TooltipProvider } from "./TooltipProvider.vue.js";
124
124
  export { confirm, toast } from "./feedback-store.js";
125
125
  export { useConfirm, useToast } from "./feedback-context.js";
126
+ export { default as DatePicker } from "./DatePicker.vue.js";
package/dist/uni/index.js CHANGED
@@ -123,3 +123,4 @@ export { default as ToastProvider } from "./ToastProvider.vue";
123
123
  export { default as TooltipProvider } from "./TooltipProvider.vue";
124
124
  export { confirm, toast } from "./feedback-store.js";
125
125
  export { useConfirm, useToast } from "./feedback-context.js";
126
+ export { default as DatePicker } from "./DatePicker.vue";
@@ -97,6 +97,13 @@ export declare const uniComponentManifest: readonly [{
97
97
  readonly tests: readonly ["src/parity.test.ts: native host mount", "src/advanced-fields.test.ts: actual advanced field interactions and owner rejection"];
98
98
  readonly status: "partial";
99
99
  readonly deviceE2E: false;
100
+ }, {
101
+ readonly name: "DatePicker";
102
+ readonly scope: "YYYY-MM-DD controlled strings/null/empty, defaultValue, strict typing and lenient blur normalization, valid-date and minDate/maxDate checks, clearing, field locks, label and open/change events. Popup MonthCalendar with month navigation; update:modelValue supports v-model.";
103
+ readonly limitations: readonly ["Native focus and popup placement need device validation."];
104
+ readonly tests: readonly ["src/date-picker.test.ts", "spike/browser/date-picker.spec.ts"];
105
+ readonly status: "partial";
106
+ readonly deviceE2E: false;
100
107
  }, {
101
108
  readonly name: "TimePicker";
102
109
  readonly scope: "Typed HH:mm or HH:mm:ss, hour/minute/second steps, normalized constraints, locale labels, clear, keyboard time columns, original string change and open-change notifications; measured collision-aware popup.";
@@ -170,6 +170,14 @@ export const uniComponentManifest = [
170
170
  status: "partial",
171
171
  deviceE2E: false,
172
172
  },
173
+ {
174
+ name: "DatePicker",
175
+ scope: "YYYY-MM-DD controlled strings/null/empty, defaultValue, strict typing and lenient blur normalization, valid-date and minDate/maxDate checks, clearing, field locks, label and open/change events. Popup MonthCalendar with month navigation; update:modelValue supports v-model.",
176
+ limitations: ["Native focus and popup placement need device validation."],
177
+ tests: ["src/date-picker.test.ts", "spike/browser/date-picker.spec.ts"],
178
+ status: "partial",
179
+ deviceE2E: false,
180
+ },
173
181
  {
174
182
  name: "TimePicker",
175
183
  scope: "Typed HH:mm or HH:mm:ss, hour/minute/second steps, normalized constraints, locale labels, clear, keyboard time columns, original string change and open-change notifications; measured collision-aware popup.",
@@ -0,0 +1,36 @@
1
+ import { DatePickerProps } from './types.js';
2
+ declare const __VLS_export: import('vue').DefineComponent<DatePickerProps, {
3
+ /** The native `<input>` (the React `ref`) */
4
+ input: import('vue').ShallowRef<HTMLInputElement | null, HTMLInputElement | null>;
5
+ focus: () => void | undefined;
6
+ blur: () => void | undefined;
7
+ }, {}, {}, {}, import('vue').ComponentOptionsMixin, import('vue').ComponentOptionsMixin, {
8
+ change: (value: string) => any;
9
+ "update:modelValue": (value: string) => any;
10
+ openChange: (open: boolean) => any;
11
+ }, string, import('vue').PublicProps, Readonly<DatePickerProps> & Readonly<{
12
+ onChange?: ((value: string) => any) | undefined;
13
+ "onUpdate:modelValue"?: ((value: string) => any) | undefined;
14
+ onOpenChange?: ((open: boolean) => any) | undefined;
15
+ }>, {
16
+ name: string;
17
+ required: boolean;
18
+ placeholder: string;
19
+ label: string;
20
+ defaultValue: string;
21
+ id: string;
22
+ disabled: boolean;
23
+ invalid: boolean;
24
+ readOnly: boolean;
25
+ clearable: boolean;
26
+ size: "small" | "medium" | "large";
27
+ modelValue: string | null;
28
+ ariaLabel: string;
29
+ ariaLabelledby: string;
30
+ ariaDescribedby: string;
31
+ minDate: string;
32
+ maxDate: string;
33
+ locale: string;
34
+ }, {}, {}, {}, string, import('vue').ComponentProvideOptions, false, {}, any>;
35
+ declare const _default: typeof __VLS_export;
36
+ export default _default;
@@ -0,0 +1,7 @@
1
+ import e from "./DatePicker.vue_vue_type_script_setup_true_lang.js";
2
+ //#region src/components/DatePicker/DatePicker.vue
3
+ var t = e;
4
+ //#endregion
5
+ export { t as default };
6
+
7
+ //# sourceMappingURL=DatePicker.vue.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"DatePicker.vue.js","names":["_sfc_main","DatePicker_vue_vue_type_script_setup_true_lang_default","DatePicker_default"],"sources":["../../../../../vue/src/components/DatePicker/DatePicker.vue"],"sourcesContent":["<script setup lang=\"ts\">\n/** A date input with an accessible popup calendar; values use YYYY-MM-DD. */\nimport {\n computed,\n nextTick,\n onMounted,\n provide,\n ref,\n shallowRef,\n unref,\n useId,\n} from \"vue\";\nimport {\n addDays,\n dayKey,\n localDate,\n monthStart,\n parseDayKey,\n sameMonth,\n} from \"@minerva/core\";\nimport styles from \"@react-styles/components/DatePicker/datePicker.module.scss\";\nimport iconButtonStyles from \"@react-styles/components/IconButton/iconButton.module.scss\";\nimport { hooks } from \"../../internal/hooks\";\nimport {\n IconCalendar,\n IconChevronLeft,\n IconChevronRight,\n IconX,\n} from \"../../internal/icons\";\nimport { useControllable } from \"../../internal/controllable\";\nimport FloatingPanel from \"../../internal/FloatingPanel.vue\";\nimport { useLayerParent } from \"../../internal/scope\";\nimport {\n FORM_CONTROL_KEY,\n useFormControlContext,\n useFormControlProps,\n} from \"../../internal/form-control\";\nimport { useI18n } from \"../../config/useI18n\";\nimport { Input } from \"../Input\";\nimport { logicalArrowKey } from \"../../internal/direction\";\nimport { adjacentTabbable, tabLeavesPanel } from \"../TimePicker/tabbing\";\nimport type { DatePickerEmits, DatePickerProps } from \"./types\";\n\ndefineOptions({ name: \"DatePicker\", inheritAttrs: false });\n\nconst props = withDefaults(defineProps<DatePickerProps>(), {\n modelValue: undefined,\n defaultValue: undefined,\n placeholder: undefined,\n label: undefined,\n ariaLabel: undefined,\n ariaLabelledby: undefined,\n ariaDescribedby: undefined,\n id: undefined,\n required: undefined,\n readOnly: undefined,\n invalid: undefined,\n name: \"date-picker\",\n disabled: undefined,\n clearable: true,\n size: \"medium\",\n minDate: undefined,\n maxDate: undefined,\n locale: undefined,\n});\nconst emit = defineEmits<DatePickerEmits>();\n\nconst { t, language } = useI18n();\nconst fc = useFormControlContext();\n// The field state is resolved here (explicit props win over the\n// FormControl), so the inner Input must not merge it again.\nprovide(FORM_CONTROL_KEY, null as never);\nconst fieldProps = useFormControlProps(() => ({\n id: props.id,\n \"aria-describedby\": props.ariaDescribedby,\n}));\n\nconst disabled = computed(() => props.disabled ?? fc?.disabled.value ?? false);\nconst readOnly = computed(() => props.readOnly ?? fc?.readOnly.value ?? false);\nconst required = computed(() => props.required ?? fc?.required.value ?? false);\nconst invalid = computed(() => props.invalid ?? fc?.invalid.value ?? false);\nconst accessibleName = computed(\n () => props.label ?? props.ariaLabel ?? t(\"datePicker.label\"),\n);\n// A FormLabel names the input unless `label` / `aria-label` is given; the\n// aria-label stays as fallback (aria-labelledby wins when its target\n// exists, and is ignored when it does not).\nconst labelledBy = computed(\n () =>\n props.ariaLabelledby ??\n (fc && !props.label && !props.ariaLabel ? fc.labelId.value : undefined),\n);\n\nconst current = useControllable<string | null>(props, \"modelValue\", {\n defaultProp: \"defaultValue\",\n fallback: \"\",\n name: \"DatePicker\",\n});\nconst open = ref(false);\nconst setOpen = (next: boolean) => {\n if (next === open.value) return;\n open.value = next;\n emit(\"openChange\", next);\n};\nconst panelOpen = computed(\n () => open.value && !disabled.value && !readOnly.value,\n);\n\n// Text being typed; `null` = show the formatted value\nconst draft = ref<string | null>(null);\nconst field = ref<HTMLDivElement | null>(null);\nconst input = shallowRef<HTMLInputElement | null>(null);\nconst floating = ref<InstanceType<typeof FloatingPanel> | null>(null);\n// Tab moves on within the enclosing layer (e.g. a Modal), else the page.\nconst tabContainer = useLayerParent();\n\nonMounted(() => {\n input.value = field.value?.querySelector(\"input\") ?? null;\n});\n\nconst headingId = useId();\nconst month = ref(monthStart(parseDayKey(current.value ?? \"\") ?? new Date()));\nconst focusedKey = ref(\"\");\nconst weekdays = [\"mon\", \"tue\", \"wed\", \"thu\", \"fri\", \"sat\", \"sun\"] as const;\nconst todayKey = dayKey(new Date());\nconst heading = computed(() =>\n new Intl.DateTimeFormat(props.locale ?? language.value, {\n year: \"numeric\",\n month: \"long\",\n }).format(month.value),\n);\nconst days = computed(() => {\n const first = monthStart(month.value);\n const start = addDays(first, -((first.getDay() + 6) % 7));\n return Array.from({ length: 42 }, (_, i) => addDays(start, i));\n});\nconst weeks = computed(() =>\n Array.from({ length: 6 }, (_, i) => days.value.slice(i * 7, i * 7 + 7)),\n);\nconst isDayDisabled = (key: string) =>\n !!(\n (props.minDate && key < props.minDate) ||\n (props.maxDate && key > props.maxDate)\n );\nconst activeKey = computed(() => {\n const keys = days.value.map(dayKey);\n return [\n focusedKey.value,\n current.value,\n todayKey,\n dayKey(month.value),\n ...keys,\n ].find((key) => key && keys.includes(key) && !isDayDisabled(key));\n});\nfunction commit(next: string) {\n current.value = next;\n emit(\"change\", next);\n}\nfunction syncMonth() {\n const date = parseDayKey(current.value ?? \"\");\n if (date) month.value = monthStart(date);\n}\nfunction handleInputChange(value: string | number) {\n if (disabled.value || readOnly.value) return;\n const text = String(value);\n draft.value = text;\n if (text === \"\") {\n commit(\"\");\n return;\n }\n const date = parseDayKey(text, true);\n if (date && !isDayDisabled(dayKey(date))) {\n commit(dayKey(date));\n month.value = monthStart(date);\n }\n}\nfunction handleInputBlur() {\n if (draft.value === null) return;\n const text = draft.value.trim();\n if (!disabled.value && !readOnly.value) {\n if (!text) {\n if (current.value) commit(\"\");\n } else {\n const date = parseDayKey(text, false);\n if (\n date &&\n !isDayDisabled(dayKey(date)) &&\n dayKey(date) !== current.value\n ) {\n commit(dayKey(date));\n month.value = monthStart(date);\n }\n }\n }\n draft.value = null;\n}\nfunction handleClear() {\n if (disabled.value || readOnly.value) return;\n draft.value = null;\n commit(\"\");\n input.value?.focus();\n}\nfunction selectDate(date: Date) {\n if (disabled.value || readOnly.value || isDayDisabled(dayKey(date))) return;\n draft.value = null;\n commit(dayKey(date));\n month.value = monthStart(date);\n setOpen(false);\n input.value?.focus();\n}\nfunction toggle() {\n if (disabled.value || readOnly.value) return;\n if (!open.value) syncMonth();\n setOpen(!open.value);\n}\nasync function focusDay(key?: string) {\n await nextTick();\n const panel = unref(floating.value?.element);\n (key\n ? panel?.querySelector<HTMLElement>(`[data-date=\"${key}\"]`)\n : panel?.querySelector<HTMLElement>('[role=\"gridcell\"][tabindex=\"0\"]')\n )?.focus();\n}\nfunction handleDayKeyDown(event: KeyboardEvent, date: Date) {\n if (disabled.value || readOnly.value) return;\n if (event.key === \"Enter\" || event.key === \" \") {\n event.preventDefault();\n if (!event.repeat) selectDate(date);\n return;\n }\n let target: Date;\n const weekday = (date.getDay() + 6) % 7;\n switch (logicalArrowKey(event.key, event.currentTarget as HTMLElement)) {\n case \"ArrowLeft\":\n target = addDays(date, -1);\n break;\n case \"ArrowRight\":\n target = addDays(date, 1);\n break;\n case \"ArrowUp\":\n target = addDays(date, -7);\n break;\n case \"ArrowDown\":\n target = addDays(date, 7);\n break;\n case \"Home\":\n target = addDays(date, -weekday);\n break;\n case \"End\":\n target = addDays(date, 6 - weekday);\n break;\n case \"PageUp\":\n case \"PageDown\": {\n const next = monthStart(\n date,\n (event.key === \"PageUp\" ? -1 : 1) * (event.shiftKey ? 12 : 1),\n );\n target = localDate(\n next.getFullYear(),\n next.getMonth(),\n Math.min(date.getDate(), addDays(monthStart(next, 1), -1).getDate()),\n );\n break;\n }\n default:\n return;\n }\n event.preventDefault();\n focusedKey.value = dayKey(target);\n if (!sameMonth(target, month.value)) month.value = monthStart(target);\n void focusDay(dayKey(target));\n}\n\n// Clicking the input toggles the panel. The handler only reacts to clicks\n// on the inner <input>, which has its own keyboard support (ArrowDown opens\n// the panel; Escape closes it), so the wrapper is not a control.\nfunction handleRootClick(event: MouseEvent) {\n if (input.value && event.target === input.value) toggle();\n}\n\nfunction handleInputKeyDown(event: KeyboardEvent) {\n if (event.key !== \"ArrowDown\" || disabled.value || readOnly.value) return;\n event.preventDefault();\n if (!open.value) {\n syncMonth();\n focusedKey.value = current.value ?? \"\";\n setOpen(true);\n }\n void focusDay();\n}\n\n// The portalled panel sits after the input in the Tab order: Tab past its\n// last control continues after the input (its clear button, then the rest of\n// the page); Shift+Tab before its first control returns to the input.\nfunction handlePanelKeyDown(event: KeyboardEvent) {\n const panel = event.currentTarget as HTMLElement;\n const el = input.value;\n if (\n !el ||\n event.key !== \"Tab\" ||\n event.altKey ||\n event.ctrlKey ||\n event.metaKey ||\n !tabLeavesPanel(panel, event.target as Element, event.shiftKey)\n )\n return;\n event.preventDefault();\n const next = event.shiftKey\n ? el\n : (adjacentTabbable(\n el,\n tabContainer?.value ?? el.ownerDocument.body,\n false,\n ) ?? el);\n next.focus();\n setOpen(false);\n}\n\nconst displayValue = computed(() => draft.value ?? current.value ?? \"\");\nconst showClear = computed(\n () =>\n props.clearable && !!current.value && !disabled.value && !readOnly.value,\n);\n\ndefineExpose({\n /** The native `<input>` (the React `ref`) */\n input,\n focus: () => input.value?.focus(),\n blur: () => input.value?.blur(),\n});\n</script>\n\n<template>\n <div\n ref=\"field\"\n :class=\"styles.datePicker\"\n v-bind=\"{\n ...$attrs,\n ...hooks('date-picker', 'root', {\n state: panelOpen ? 'open' : 'closed',\n disabled,\n readonly: readOnly,\n invalid,\n size,\n }),\n }\"\n @click=\"handleRootClick\"\n >\n <Input\n :model-value=\"displayValue\"\n :placeholder=\"placeholder ?? t('datePicker.placeholder')\"\n :id=\"fieldProps.id\"\n :aria-label=\"accessibleName\"\n :aria-labelledby=\"labelledBy\"\n :aria-describedby=\"fieldProps['aria-describedby']\"\n :aria-invalid=\"invalid || undefined\"\n :aria-readonly=\"readOnly || undefined\"\n :required=\"required\"\n :read-only=\"readOnly\"\n :name=\"name\"\n :disabled=\"disabled\"\n :size=\"size\"\n @update:model-value=\"handleInputChange\"\n @blur=\"handleInputBlur\"\n @keydown=\"handleInputKeyDown\"\n >\n <template #suffix>\n <button\n v-if=\"showClear\"\n type=\"button\"\n :class=\"[\n iconButtonStyles.iconButton,\n iconButtonStyles.neutral,\n iconButtonStyles['variant-ghost'],\n iconButtonStyles.small,\n iconButtonStyles.circle,\n styles.clearButton,\n ]\"\n tabindex=\"0\"\n :aria-label=\"t('datePicker.clear')\"\n v-bind=\"\n hooks('icon-button', 'root', {\n state: 'inactive',\n disabled: false,\n loading: false,\n size: 'small',\n variant: 'ghost',\n color: 'neutral',\n shape: 'circle',\n })\n \"\n @click=\"handleClear\"\n >\n <span\n :class=\"iconButtonStyles.glyph\"\n aria-hidden=\"true\"\n v-bind=\"hooks('icon-button', 'icon')\"\n >\n <IconX />\n </span>\n </button>\n <span\n v-else\n :class=\"styles.calendarIcon\"\n aria-hidden=\"true\"\n v-bind=\"hooks('date-picker', 'icon')\"\n >\n <IconCalendar />\n </span>\n </template>\n </Input>\n <FloatingPanel\n ref=\"floating\"\n :open=\"panelOpen\"\n :anchor=\"input\"\n placement=\"bottom-start\"\n :branches=\"() => [field]\"\n :return-focus-on-escape=\"() => input\"\n focusable\n role=\"dialog\"\n tabindex=\"-1\"\n :aria-label=\"accessibleName\"\n :aria-labelledby=\"labelledBy\"\n :class=\"styles.popup\"\n v-bind=\"hooks('date-picker', 'content', { state: 'open' })\"\n @dismiss=\"setOpen(false)\"\n @keydown=\"handlePanelKeyDown\"\n >\n <div :class=\"styles.panel\">\n <div :class=\"styles.header\">\n <h2 :id=\"headingId\" :class=\"styles.heading\" aria-live=\"polite\">\n {{ heading }}\n </h2>\n <div :class=\"styles.navGroup\">\n <button\n type=\"button\"\n :class=\"styles.navButton\"\n :aria-label=\"t('monthCalendar.previousMonth')\"\n @click=\"month = monthStart(month, -1)\"\n >\n <IconChevronLeft aria-hidden=\"true\" focusable=\"false\" />\n </button>\n <button\n type=\"button\"\n :class=\"styles.navButton\"\n :aria-label=\"t('monthCalendar.nextMonth')\"\n @click=\"month = monthStart(month, 1)\"\n >\n <IconChevronRight aria-hidden=\"true\" focusable=\"false\" />\n </button>\n </div>\n </div>\n <div role=\"grid\" :aria-labelledby=\"headingId\" :class=\"styles.grid\">\n <div role=\"row\" :class=\"styles.week\">\n <div\n v-for=\"day in weekdays\"\n :key=\"day\"\n role=\"columnheader\"\n :class=\"styles.weekday\"\n >\n {{ t(`monthCalendar.weekdays.${day}`) }}\n </div>\n </div>\n <div\n v-for=\"(week, index) in weeks\"\n :key=\"index\"\n role=\"row\"\n :class=\"styles.week\"\n >\n <div\n v-for=\"date in week\"\n :key=\"dayKey(date)\"\n role=\"gridcell\"\n :class=\"styles.day\"\n :data-date=\"dayKey(date)\"\n :data-outside=\"!sameMonth(date, month) ? '' : undefined\"\n :aria-label=\"dayKey(date)\"\n :aria-selected=\"current === dayKey(date)\"\n :aria-current=\"dayKey(date) === todayKey ? 'date' : undefined\"\n :aria-disabled=\"isDayDisabled(dayKey(date)) || undefined\"\n :tabindex=\"dayKey(date) === activeKey ? 0 : -1\"\n @focus=\"focusedKey = dayKey(date)\"\n @click=\"selectDate(date)\"\n @keydown=\"handleDayKeyDown($event, date)\"\n >\n {{ date.getDate() }}\n </div>\n </div>\n </div>\n <div :class=\"styles.footer\">\n <button\n type=\"button\"\n :class=\"styles.footerButton\"\n :disabled=\"isDayDisabled(todayKey)\"\n @click=\"selectDate(new Date())\"\n >\n {{ t(\"datePicker.today\") }}\n </button>\n <button\n v-if=\"clearable && current\"\n type=\"button\"\n :class=\"styles.footerButton\"\n @click=\"\n handleClear();\n setOpen(false);\n \"\n >\n {{ t(\"datePicker.clear\") }}\n </button>\n </div>\n </div>\n </FloatingPanel>\n </div>\n</template>\n"],"mappings":""}