@eos-ui/vue 0.4.0 → 0.5.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.
Files changed (96) hide show
  1. package/README.md +4 -4
  2. package/dist/component-names.js +1 -1
  3. package/dist/component-names.js.map +1 -1
  4. package/dist/components/Actions/EActions.js.map +1 -1
  5. package/dist/components/Actions/EActions.vue.d.ts +1 -1
  6. package/dist/components/Actions/EActions.vue_vue_type_script_setup_true_lang.js.map +1 -1
  7. package/dist/components/Avatar/EAvatar.js.map +1 -1
  8. package/dist/components/Avatar/EAvatar.vue.d.ts +1 -1
  9. package/dist/components/Avatar/EAvatar.vue_vue_type_script_setup_true_lang.js.map +1 -1
  10. package/dist/components/Button/EButton.js.map +1 -1
  11. package/dist/components/Button/EButton.vue.d.ts +2 -0
  12. package/dist/components/Button/EButton.vue_vue_type_script_setup_true_lang.js +64 -29
  13. package/dist/components/Button/EButton.vue_vue_type_script_setup_true_lang.js.map +1 -1
  14. package/dist/components/Calendar/ECalendar.js.map +1 -1
  15. package/dist/components/Calendar/ECalendar.vue.d.ts +1 -1
  16. package/dist/components/Calendar/ECalendar.vue_vue_type_script_setup_true_lang.js.map +1 -1
  17. package/dist/components/Checkbox/ECheckbox.js.map +1 -1
  18. package/dist/components/Checkbox/ECheckbox.vue.d.ts +1 -1
  19. package/dist/components/Checkbox/ECheckbox.vue_vue_type_script_setup_true_lang.js.map +1 -1
  20. package/dist/components/Combobox/EComboboxBase.js.map +1 -1
  21. package/dist/components/Combobox/EComboboxBase.vue_vue_type_script_setup_true_lang.js +4 -8
  22. package/dist/components/Combobox/EComboboxBase.vue_vue_type_script_setup_true_lang.js.map +1 -1
  23. package/dist/components/Combobox/types.d.ts +2 -2
  24. package/dist/components/DataGrid/EDataGrid.js.map +1 -1
  25. package/dist/components/DataGrid/EDataGrid.vue.d.ts +1 -1
  26. package/dist/components/DataGrid/EDataGrid.vue_vue_type_script_setup_true_lang.js +1 -0
  27. package/dist/components/DataGrid/EDataGrid.vue_vue_type_script_setup_true_lang.js.map +1 -1
  28. package/dist/components/DescriptionList/EDescriptionList.js.map +1 -1
  29. package/dist/components/DescriptionList/EDescriptionList.vue_vue_type_script_setup_true_lang.js +2 -2
  30. package/dist/components/DescriptionList/EDescriptionList.vue_vue_type_script_setup_true_lang.js.map +1 -1
  31. package/dist/components/Dialog/EDialog.js.map +1 -1
  32. package/dist/components/Dialog/EDialog.vue_vue_type_script_setup_true_lang.js.map +1 -1
  33. package/dist/components/Drawer/EDrawer.js.map +1 -1
  34. package/dist/components/Drawer/EDrawer.vue_vue_type_script_setup_true_lang.js.map +1 -1
  35. package/dist/components/EmptyState/EEmptyState.js.map +1 -1
  36. package/dist/components/EmptyState/EEmptyState.vue.d.ts +1 -1
  37. package/dist/components/EmptyState/EEmptyState.vue_vue_type_script_setup_true_lang.js.map +1 -1
  38. package/dist/components/Grid/EGrid.js.map +1 -1
  39. package/dist/components/Grid/EGrid.vue.d.ts +1 -1
  40. package/dist/components/Grid/EGrid.vue_vue_type_script_setup_true_lang.js.map +1 -1
  41. package/dist/components/IconButton/EIconButton.js.map +1 -1
  42. package/dist/components/IconButton/EIconButton.vue_vue_type_script_setup_true_lang.js.map +1 -1
  43. package/dist/components/Inline/EInline.js.map +1 -1
  44. package/dist/components/Inline/EInline.vue.d.ts +1 -1
  45. package/dist/components/Inline/EInline.vue_vue_type_script_setup_true_lang.js.map +1 -1
  46. package/dist/components/Kbd/EKbd.js.map +1 -1
  47. package/dist/components/Kbd/EKbd.vue_vue_type_script_setup_true_lang.js.map +1 -1
  48. package/dist/components/NavList/ENavList.js.map +1 -1
  49. package/dist/components/NavList/ENavList.vue_vue_type_script_setup_true_lang.js.map +1 -1
  50. package/dist/components/Notice/ENotice.js.map +1 -1
  51. package/dist/components/Notice/ENotice.vue_vue_type_script_setup_true_lang.js.map +1 -1
  52. package/dist/components/OtpField/EOtpField.js.map +1 -1
  53. package/dist/components/OtpField/EOtpField.vue_vue_type_script_setup_true_lang.js.map +1 -1
  54. package/dist/components/Pagination/EPagination.js.map +1 -1
  55. package/dist/components/Pagination/EPagination.vue_vue_type_script_setup_true_lang.js.map +1 -1
  56. package/dist/components/PasswordField/EPasswordField.js.map +1 -1
  57. package/dist/components/PasswordField/EPasswordField.vue_vue_type_script_setup_true_lang.js.map +1 -1
  58. package/dist/components/SearchBar/ESearchBar.js.map +1 -1
  59. package/dist/components/SearchBar/ESearchBar.vue.d.ts +1 -1
  60. package/dist/components/SearchBar/ESearchBar.vue_vue_type_script_setup_true_lang.js.map +1 -1
  61. package/dist/components/Segmented/ESegmented.js.map +1 -1
  62. package/dist/components/Segmented/ESegmented.vue_vue_type_script_setup_true_lang.js.map +1 -1
  63. package/dist/components/Select/ESelectControl.js.map +1 -1
  64. package/dist/components/Select/ESelectControl.vue_vue_type_script_setup_true_lang.js.map +1 -1
  65. package/dist/components/SignaturePad/ESignaturePad.js.map +1 -1
  66. package/dist/components/SignaturePad/ESignaturePad.vue_vue_type_script_setup_true_lang.js.map +1 -1
  67. package/dist/components/Stack/EStack.js.map +1 -1
  68. package/dist/components/Stack/EStack.vue.d.ts +1 -1
  69. package/dist/components/Stack/EStack.vue_vue_type_script_setup_true_lang.js.map +1 -1
  70. package/dist/components/Stamp/EStamp.js.map +1 -1
  71. package/dist/components/Stamp/EStamp.vue.d.ts +2 -2
  72. package/dist/components/Stamp/EStamp.vue_vue_type_script_setup_true_lang.js +2 -2
  73. package/dist/components/Stamp/EStamp.vue_vue_type_script_setup_true_lang.js.map +1 -1
  74. package/dist/components/Stepper/EStepper.js.map +1 -1
  75. package/dist/components/Stepper/EStepper.vue_vue_type_script_setup_true_lang.js.map +1 -1
  76. package/dist/components/Surface/ESurface.js.map +1 -1
  77. package/dist/components/Surface/ESurface.vue.d.ts +1 -1
  78. package/dist/components/Surface/ESurface.vue_vue_type_script_setup_true_lang.js.map +1 -1
  79. package/dist/components/Switch/ESwitch.js.map +1 -1
  80. package/dist/components/Switch/ESwitch.vue_vue_type_script_setup_true_lang.js.map +1 -1
  81. package/dist/components/Table/ETable.js +8 -0
  82. package/dist/components/Table/ETable.js.map +1 -0
  83. package/dist/components/Table/ETable.vue.d.ts +25 -0
  84. package/dist/components/Table/ETable.vue_vue_type_script_setup_true_lang.js +28 -0
  85. package/dist/components/Table/ETable.vue_vue_type_script_setup_true_lang.js.map +1 -0
  86. package/dist/components/Table/index.d.ts +1 -0
  87. package/dist/components/Tabs/ETabs.js.map +1 -1
  88. package/dist/components/Tabs/ETabs.vue.d.ts +10 -2
  89. package/dist/components/Tabs/ETabs.vue_vue_type_script_setup_true_lang.js +11 -3
  90. package/dist/components/Tabs/ETabs.vue_vue_type_script_setup_true_lang.js.map +1 -1
  91. package/dist/components/Upload/EUpload.js.map +1 -1
  92. package/dist/components/Upload/EUpload.vue_vue_type_script_setup_true_lang.js.map +1 -1
  93. package/dist/index.d.ts +1 -0
  94. package/dist/index.js +10 -9
  95. package/dist/style.css +553 -174
  96. package/package.json +3 -2
@@ -1 +1 @@
1
- {"version":3,"file":"EOtpField.vue_vue_type_script_setup_true_lang.js","names":["_useModel","_openBlock","_createBlock","EField","_mergeProps","_unref","_withCtx","_createElementVNode","_createElementBlock","_Fragment","_renderList","_createCommentVNode","EField_default","_hoisted_1","_hoisted_2","_hoisted_3","_hoisted_4","EOtpField_vue_vue_type_script_setup_true_lang_default","\"modelValue\"","\"modelModifiers\"","__expose","__emit","props","__props","emit","model","useModel","t","useMessages","attrs","useFieldAttrs","numeric","computed","refs","clean","text","s","value","live","v","commit","next","prev","focusAt","i","without","put","chars","from","onInput","target","e","raw","k","onKey","onFocus","onPaste","onMounted","openBlock","createBlock","mergeProps","unref","withCtx","createElementVNode","field","createElementBlock","Fragment","renderList","createCommentVNode","el","$event"],"sources":["../../../src/components/OtpField/EOtpField.vue"],"sourcesContent":["<script setup lang=\"ts\">\nimport { computed, onMounted, watch } from \"vue\";\nimport EField from \"../Field/EField.vue\";\nimport { useMessages } from \"../../config.js\";\nimport { useFieldAttrs } from \"../../composables/useFieldAttrs.js\";\nimport \"../../styles/base.css\";\nimport \"../TextField/input.css\";\n\ndefineOptions({ inheritAttrs: false });\n\nconst props = withDefaults(\n defineProps<{\n /** The field's label. @default \"Verification code\" */\n label?: string;\n /** Keep the label for screen readers and remove it from the page. */\n hideLabel?: boolean;\n /** How many characters: the number of boxes. */\n length?: number;\n /** `numeric` opens the number pad; `text` takes letters and digits, upper-cased. */\n inputmode?: \"numeric\" | \"text\";\n /** A gap between groups: 6 with 3 reads 123 456. */\n groupSize?: number;\n /** The name submitted with a form (the whole code), through a hidden input. */\n name?: string;\n /** Start in the first empty box. */\n autoFocus?: boolean;\n /** Help under the boxes, read with each box. */\n hint?: string;\n /** What to fix. Replaces the hint, marks every box invalid and is announced. */\n error?: string;\n /** A word beside the label, and the `required` attribute on every box. */\n required?: boolean;\n /** A word beside the label. Flag whichever is rarer. */\n optional?: boolean;\n /** Disables every box. */\n disabled?: boolean;\n /** The id of the first box; the label and hint ids are built from it. @default generated */\n id?: string;\n }>(),\n { length: 6, inputmode: \"numeric\", groupSize: 0 },\n);\n\nconst emit = defineEmits<{\n /** Once, when the last box fills. */\n complete: [code: string];\n}>();\n\n/** The code typed so far. */\nconst model = defineModel<string>({ default: \"\" });\n\nconst t = useMessages();\nconst attrs = useFieldAttrs();\nconst numeric = computed(() => props.inputmode !== \"text\");\nconst refs: (HTMLInputElement | null)[] = [];\n\nfunction clean(s: unknown): string {\n const text = String(s ?? \"\");\n return (numeric.value ? text.replace(/\\D/g, \"\") : text.replace(/[^a-z0-9]/gi, \"\").toUpperCase()).slice(\n 0,\n props.length,\n );\n}\nconst value = computed(() => clean(model.value));\n\nlet live = value.value;\nwatch(value, (v) => (live = v), { flush: \"sync\" });\n\nfunction commit(next: string) {\n next = clean(next);\n const prev = live;\n live = next;\n model.value = next;\n if (next.length === props.length && prev !== next) emit(\"complete\", next);\n}\nfunction focusAt(i: number) {\n refs[Math.max(0, Math.min(props.length - 1, i))]?.focus();\n}\nconst without = (v: string, i: number) => v.slice(0, i) + v.slice(i + 1);\nfunction put(i: number, text: string) {\n const chars = clean(text);\n if (!chars) return;\n const from = chars.length >= props.length ? 0 : Math.min(i, live.length);\n commit(live.slice(0, from) + chars);\n focusAt(from + chars.length);\n}\nfunction onInput(i: number, e: Event) {\n const target = e.target as HTMLInputElement;\n const v = live;\n let raw = target.value;\n if (!raw) {\n commit(without(v, i));\n return;\n }\n if (v[i] && raw.length === 2) {\n const k = raw.indexOf(v[i]!);\n raw = k >= 0 ? without(raw, k) : raw.charAt(1);\n }\n const chars = clean(raw);\n if (!chars) {\n target.value = live[i] ?? \"\";\n return;\n }\n if (chars.length === 1 && i < v.length) {\n commit(v.slice(0, i) + chars + v.slice(i + 1));\n focusAt(i + 1);\n } else put(i, chars);\n target.value = live[i] ?? \"\";\n}\nfunction onKey(i: number, e: KeyboardEvent) {\n const v = live;\n const k = e.key;\n if (k === \"Backspace\") {\n e.preventDefault();\n if (v[i]) {\n commit(without(v, i));\n focusAt(i);\n } else if (i > 0) {\n commit(without(v, i - 1));\n focusAt(i - 1);\n }\n } else if (k === \"Delete\") {\n e.preventDefault();\n commit(without(v, i));\n } else if (k === \"ArrowLeft\") {\n e.preventDefault();\n focusAt(i - 1);\n } else if (k === \"ArrowRight\") {\n e.preventDefault();\n focusAt(Math.min(i + 1, v.length));\n } else if (k === \"Home\") {\n e.preventDefault();\n focusAt(0);\n } else if (k === \"End\") {\n e.preventDefault();\n focusAt(v.length);\n }\n}\nfunction onFocus(i: number) {\n if (i > live.length) focusAt(live.length);\n}\nfunction onPaste(i: number, e: ClipboardEvent) {\n e.preventDefault();\n put(i, e.clipboardData?.getData(\"text\") ?? \"\");\n}\n\nonMounted(() => {\n if (props.autoFocus) focusAt(live.length);\n});\n\ndefineExpose({\n focus: () => focusAt(live.length),\n});\n</script>\n\n<template>\n <EField\n v-bind=\"attrs.wrapper()\"\n :id=\"id\"\n :label=\"label || t('verificationCode')\"\n :hide-label=\"hideLabel\"\n :hint=\"hint\"\n :error=\"error\"\n :required=\"required\"\n :optional=\"optional\"\n >\n <template #default=\"field\">\n <div role=\"group\" :aria-labelledby=\"`${field.id}-label`\" class=\"e-otp\" v-bind=\"attrs.input()\">\n <template v-for=\"i in length\" :key=\"i\">\n <span v-if=\"groupSize && i > 1 && (i - 1) % groupSize === 0\" class=\"e-otp-sep\" aria-hidden=\"true\" />\n <input\n :id=\"i === 1 ? field.id : undefined\"\n :ref=\"(el) => (refs[i - 1] = el as HTMLInputElement | null)\"\n class=\"e-input e-otp-box\"\n type=\"text\"\n :inputmode=\"numeric ? 'numeric' : 'text'\"\n :autocomplete=\"i === 1 ? 'one-time-code' : 'off'\"\n autocapitalize=\"characters\"\n :spellcheck=\"false\"\n :value=\"value[i - 1] || ''\"\n :disabled=\"disabled\"\n :required=\"required\"\n :data-filled=\"value[i - 1] ? '' : undefined\"\n :aria-label=\"t(numeric ? 'otpDigit' : 'otpChar', { n: i, total: length })\"\n :aria-invalid=\"field.ariaInvalid\"\n :aria-describedby=\"field.ariaDescribedby\"\n @input=\"onInput(i - 1, $event)\"\n @keydown=\"onKey(i - 1, $event)\"\n @focus=\"onFocus(i - 1)\"\n @paste=\"onPaste(i - 1, $event)\"\n />\n </template>\n <input v-if=\"name\" type=\"hidden\" :name=\"name\" :value=\"value\" />\n </div>\n </template>\n </EField>\n</template>\n\n<style>\n@layer e.controls {\n .e-otp {\n display: flex;\n align-items: center;\n gap: var(--e-space-2);\n max-width: 100%;\n }\n\n .e-otp-sep {\n flex: none;\n width: var(--e-space-3);\n }\n\n .e-otp .e-otp-box {\n flex: 1 1 0;\n width: 0;\n min-width: 30px;\n max-width: var(--e-control-height);\n padding: 0;\n text-align: center;\n font: 500 var(--e-text-xl)/1 var(--e-font-mono);\n font-variant-numeric: tabular-nums;\n text-transform: uppercase;\n caret-color: var(--e-primary);\n }\n\n /* stylelint-disable-next-line selector-not-notation */\n .e-otp .e-otp-box[data-filled]:not(:focus):not([aria-invalid=\"true\"]) {\n border-color: var(--e-ink);\n }\n}\n</style>\n"],"mappings":"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"}
1
+ {"version":3,"file":"EOtpField.vue_vue_type_script_setup_true_lang.js","names":["_useModel","_openBlock","_createBlock","EField","_mergeProps","_unref","_withCtx","_createElementVNode","_createElementBlock","_Fragment","_renderList","_createCommentVNode","EField_default","_hoisted_1","_hoisted_2","_hoisted_3","_hoisted_4","EOtpField_vue_vue_type_script_setup_true_lang_default","\"modelValue\"","\"modelModifiers\"","__expose","__emit","props","__props","emit","model","useModel","t","useMessages","attrs","useFieldAttrs","numeric","computed","refs","clean","text","s","value","live","v","commit","next","prev","focusAt","i","without","put","chars","from","onInput","target","e","raw","k","onKey","onFocus","onPaste","onMounted","openBlock","createBlock","mergeProps","unref","withCtx","createElementVNode","field","createElementBlock","Fragment","renderList","createCommentVNode","el","$event"],"sources":["../../../src/components/OtpField/EOtpField.vue"],"sourcesContent":["<script setup lang=\"ts\">\nimport { computed, onMounted, watch } from \"vue\";\nimport EField from \"../Field/EField.vue\";\nimport { useMessages } from \"../../config.js\";\nimport { useFieldAttrs } from \"../../composables/useFieldAttrs.js\";\nimport \"../../styles/base.css\";\nimport \"../TextField/input.css\";\n\ndefineOptions({ inheritAttrs: false });\n\nconst props = withDefaults(\n defineProps<{\n /** The field's label. @default \"Verification code\" */\n label?: string;\n /** Keep the label for screen readers and remove it from the page. */\n hideLabel?: boolean;\n /** How many characters: the number of boxes. */\n length?: number;\n /** `numeric` opens the number pad; `text` takes letters and digits, upper-cased. */\n inputmode?: \"numeric\" | \"text\";\n /** A gap between groups: 6 with 3 reads 123 456. */\n groupSize?: number;\n /** The name submitted with a form (the whole code), through a hidden input. */\n name?: string;\n /** Start in the first empty box. */\n autoFocus?: boolean;\n /** Help under the boxes, read with each box. */\n hint?: string;\n /** What to fix. Replaces the hint, marks every box invalid and is announced. */\n error?: string;\n /** A word beside the label, and the `required` attribute on every box. */\n required?: boolean;\n /** A word beside the label. Flag whichever is rarer. */\n optional?: boolean;\n /** Disables every box. */\n disabled?: boolean;\n /** The id of the first box; the label and hint ids are built from it. @default generated */\n id?: string;\n }>(),\n { length: 6, inputmode: \"numeric\", groupSize: 0 },\n);\n\nconst emit = defineEmits<{\n /** Once, when the last box fills. */\n complete: [code: string];\n}>();\n\n/** The code typed so far. */\nconst model = defineModel<string>({ default: \"\" });\n\nconst t = useMessages();\nconst attrs = useFieldAttrs();\nconst numeric = computed(() => props.inputmode !== \"text\");\nconst refs: (HTMLInputElement | null)[] = [];\n\nfunction clean(s: unknown): string {\n const text = String(s ?? \"\");\n return (numeric.value ? text.replace(/\\D/g, \"\") : text.replace(/[^a-z0-9]/gi, \"\").toUpperCase()).slice(\n 0,\n props.length,\n );\n}\nconst value = computed(() => clean(model.value));\n\nlet live = value.value;\nwatch(value, (v) => (live = v), { flush: \"sync\" });\n\nfunction commit(next: string) {\n next = clean(next);\n const prev = live;\n live = next;\n model.value = next;\n if (next.length === props.length && prev !== next) emit(\"complete\", next);\n}\nfunction focusAt(i: number) {\n refs[Math.max(0, Math.min(props.length - 1, i))]?.focus();\n}\nconst without = (v: string, i: number) => v.slice(0, i) + v.slice(i + 1);\nfunction put(i: number, text: string) {\n const chars = clean(text);\n if (!chars) return;\n const from = chars.length >= props.length ? 0 : Math.min(i, live.length);\n commit(live.slice(0, from) + chars);\n focusAt(from + chars.length);\n}\nfunction onInput(i: number, e: Event) {\n const target = e.target as HTMLInputElement;\n const v = live;\n let raw = target.value;\n if (!raw) {\n commit(without(v, i));\n return;\n }\n if (v[i] && raw.length === 2) {\n const k = raw.indexOf(v[i]!);\n raw = k >= 0 ? without(raw, k) : raw.charAt(1);\n }\n const chars = clean(raw);\n if (!chars) {\n target.value = live[i] ?? \"\";\n return;\n }\n if (chars.length === 1 && i < v.length) {\n commit(v.slice(0, i) + chars + v.slice(i + 1));\n focusAt(i + 1);\n } else put(i, chars);\n target.value = live[i] ?? \"\";\n}\nfunction onKey(i: number, e: KeyboardEvent) {\n const v = live;\n const k = e.key;\n if (k === \"Backspace\") {\n e.preventDefault();\n if (v[i]) {\n commit(without(v, i));\n focusAt(i);\n } else if (i > 0) {\n commit(without(v, i - 1));\n focusAt(i - 1);\n }\n } else if (k === \"Delete\") {\n e.preventDefault();\n commit(without(v, i));\n } else if (k === \"ArrowLeft\") {\n e.preventDefault();\n focusAt(i - 1);\n } else if (k === \"ArrowRight\") {\n e.preventDefault();\n focusAt(Math.min(i + 1, v.length));\n } else if (k === \"Home\") {\n e.preventDefault();\n focusAt(0);\n } else if (k === \"End\") {\n e.preventDefault();\n focusAt(v.length);\n }\n}\nfunction onFocus(i: number) {\n if (i > live.length) focusAt(live.length);\n}\nfunction onPaste(i: number, e: ClipboardEvent) {\n e.preventDefault();\n put(i, e.clipboardData?.getData(\"text\") ?? \"\");\n}\n\nonMounted(() => {\n if (props.autoFocus) focusAt(live.length);\n});\n\ndefineExpose({\n focus: () => focusAt(live.length),\n});\n</script>\n\n<template>\n <EField\n v-bind=\"attrs.wrapper()\"\n :id=\"id\"\n :label=\"label || t('verificationCode')\"\n :hide-label=\"hideLabel\"\n :hint=\"hint\"\n :error=\"error\"\n :required=\"required\"\n :optional=\"optional\"\n >\n <template #default=\"field\">\n <div role=\"group\" :aria-labelledby=\"`${field.id}-label`\" class=\"e-otp\" v-bind=\"attrs.input()\">\n <template v-for=\"i in length\" :key=\"i\">\n <span v-if=\"groupSize && i > 1 && (i - 1) % groupSize === 0\" class=\"e-otp-sep\" aria-hidden=\"true\" />\n <input\n :id=\"i === 1 ? field.id : undefined\"\n :ref=\"(el) => (refs[i - 1] = el as HTMLInputElement | null)\"\n class=\"e-input e-otp-box\"\n type=\"text\"\n :inputmode=\"numeric ? 'numeric' : 'text'\"\n :autocomplete=\"i === 1 ? 'one-time-code' : 'off'\"\n autocapitalize=\"characters\"\n :spellcheck=\"false\"\n :value=\"value[i - 1] || ''\"\n :disabled=\"disabled\"\n :required=\"required\"\n :data-filled=\"value[i - 1] ? '' : undefined\"\n :aria-label=\"t(numeric ? 'otpDigit' : 'otpChar', { n: i, total: length })\"\n :aria-invalid=\"field.ariaInvalid\"\n :aria-describedby=\"field.ariaDescribedby\"\n @input=\"onInput(i - 1, $event)\"\n @keydown=\"onKey(i - 1, $event)\"\n @focus=\"onFocus(i - 1)\"\n @paste=\"onPaste(i - 1, $event)\"\n />\n </template>\n <input v-if=\"name\" type=\"hidden\" :name=\"name\" :value=\"value\" />\n </div>\n </template>\n </EField>\n</template>\n\n<style>\n@layer e.controls {\n .e-otp {\n display: flex;\n align-items: center;\n gap: var(--e-space-2);\n max-width: 100%;\n }\n\n .e-otp-sep {\n flex: none;\n width: var(--e-space-3);\n }\n\n .e-otp .e-otp-box {\n flex: 1 1 0;\n width: 0;\n min-width: 30px;\n max-width: var(--e-control-height);\n padding: 0;\n text-align: center;\n font: 500 var(--e-text-xl)/1 var(--e-font-mono);\n font-variant-numeric: tabular-nums;\n text-transform: uppercase;\n caret-color: var(--e-primary);\n }\n\n /* stylelint-disable-next-line selector-not-notation */\n .e-otp .e-otp-box[data-filled]:not(:focus):not([aria-invalid=\"true\"]) {\n --e-ring: var(--e-ink);\n }\n}\n</style>\n"],"mappings":"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"}
@@ -1 +1 @@
1
- {"version":3,"file":"EPagination.js","names":["_sfc_main","EPagination_vue_vue_type_script_setup_true_lang_default","EPagination_default"],"sources":["../../../src/components/Pagination/EPagination.vue"],"sourcesContent":["<script setup lang=\"ts\">\nimport { computed } from \"vue\";\nimport EButton from \"../Button/EButton.vue\";\nimport EIcon from \"../Icon/EIcon.vue\";\nimport { useMessages } from \"../../config.js\";\nimport \"../../styles/base.css\";\n\nconst props = defineProps<{\n /** How many pages there are. */\n pageCount: number;\n}>();\n\n/** The current page, from 1. */\nconst page = defineModel<number>({ default: 1 });\n\nconst t = useMessages();\n\nconst items = computed<(number | \"gap\")[]>(() => {\n const list: (number | \"gap\")[] = [];\n for (let i = 1; i <= props.pageCount; i++) {\n if (i === 1 || i === props.pageCount || Math.abs(i - page.value) <= 1) list.push(i);\n else if (list[list.length - 1] !== \"gap\") list.push(\"gap\");\n }\n return list.map((n, k) => {\n const before = list[k - 1];\n const after = list[k + 1];\n return n === \"gap\" && typeof before === \"number\" && typeof after === \"number\" && after - before === 2\n ? before + 1\n : n;\n });\n});\n</script>\n\n<template>\n <nav class=\"e-pager\" :aria-label=\"t('pagination')\">\n <EButton variant=\"outline\" icon=\"chevron-left\" :disabled=\"page <= 1\" @click=\"page = page - 1\">\n {{ t(\"previous\") }}\n </EButton>\n <ul class=\"e-pages\">\n <li v-for=\"(n, i) in items\" :key=\"i\">\n <span v-if=\"n === 'gap'\" class=\"e-page-gap\" aria-hidden=\"true\">&hellip;</span>\n <button\n v-else\n type=\"button\"\n class=\"e-page\"\n :aria-current=\"n === page ? 'page' : undefined\"\n :aria-label=\"t('pageN', { n })\"\n @click=\"page = n\"\n >\n {{ n }}\n </button>\n </li>\n </ul>\n <EButton variant=\"outline\" :disabled=\"page >= pageCount\" @click=\"page = page + 1\">\n {{ t(\"next\") }}\n <EIcon name=\"chevron-right\" />\n </EButton>\n </nav>\n</template>\n\n<style>\n@layer e.composites {\n .e-pager {\n display: flex;\n flex-wrap: wrap;\n align-items: center;\n justify-content: center;\n gap: var(--e-space-3);\n }\n\n .e-pages {\n display: flex;\n align-items: center;\n gap: var(--e-space-1);\n margin: 0;\n padding: 0;\n list-style: none;\n }\n\n .e-page {\n display: inline-grid;\n place-items: center;\n min-width: var(--e-control-height);\n height: var(--e-control-height);\n padding: 0 var(--e-space-2);\n border: var(--e-stroke-edge) solid transparent;\n border-radius: var(--e-radius-md);\n background: transparent;\n color: var(--e-ink);\n font: 500 var(--e-text-sm)/1 var(--e-font-mono);\n font-variant-numeric: tabular-nums;\n cursor: pointer;\n transition:\n background-color var(--e-duration-tap) var(--e-easing-out),\n border-color var(--e-duration-tap) var(--e-easing-out);\n }\n\n .e-page:hover {\n background: var(--e-surface-hover);\n border-color: var(--e-border-strong);\n\n }\n\n .e-page:focus-visible {\n outline: var(--e-stroke-focus) solid var(--e-focus-ring);\n outline-offset: var(--e-focus-gap);\n }\n\n .e-page[aria-current=\"page\"] {\n background: var(--e-primary);\n border-color: var(--e-primary);\n color: var(--e-on-primary);\n font-weight: 600;\n cursor: default;\n }\n\n .e-page-gap {\n display: inline-grid;\n place-items: center;\n min-width: calc(var(--e-space-6) + var(--e-space-1));\n color: var(--e-muted);\n }\n\n @media (max-width: 32rem) {\n .e-pages {\n display: none;\n }\n\n .e-pager {\n justify-content: space-between;\n }\n }\n\n @media (prefers-reduced-motion: reduce) {\n .e-page {\n transition: none;\n }\n }\n\n @media (forced-colors: active) {\n .e-page[aria-current=\"page\"] {\n forced-color-adjust: none;\n background: Highlight;\n color: HighlightText;\n }\n }\n\n @media print {\n .e-pager {\n display: none;\n }\n }\n}\n</style>\n"],"mappings":""}
1
+ {"version":3,"file":"EPagination.js","names":["_sfc_main","EPagination_vue_vue_type_script_setup_true_lang_default","EPagination_default"],"sources":["../../../src/components/Pagination/EPagination.vue"],"sourcesContent":["<script setup lang=\"ts\">\nimport { computed } from \"vue\";\nimport EButton from \"../Button/EButton.vue\";\nimport EIcon from \"../Icon/EIcon.vue\";\nimport { useMessages } from \"../../config.js\";\nimport \"../../styles/base.css\";\n\nconst props = defineProps<{\n /** How many pages there are. */\n pageCount: number;\n}>();\n\n/** The current page, from 1. */\nconst page = defineModel<number>({ default: 1 });\n\nconst t = useMessages();\n\nconst items = computed<(number | \"gap\")[]>(() => {\n const list: (number | \"gap\")[] = [];\n for (let i = 1; i <= props.pageCount; i++) {\n if (i === 1 || i === props.pageCount || Math.abs(i - page.value) <= 1) list.push(i);\n else if (list[list.length - 1] !== \"gap\") list.push(\"gap\");\n }\n return list.map((n, k) => {\n const before = list[k - 1];\n const after = list[k + 1];\n return n === \"gap\" && typeof before === \"number\" && typeof after === \"number\" && after - before === 2\n ? before + 1\n : n;\n });\n});\n</script>\n\n<template>\n <nav class=\"e-pager\" :aria-label=\"t('pagination')\">\n <EButton variant=\"outline\" icon=\"chevron-left\" :disabled=\"page <= 1\" @click=\"page = page - 1\">\n {{ t(\"previous\") }}\n </EButton>\n <ul class=\"e-pages\">\n <li v-for=\"(n, i) in items\" :key=\"i\">\n <span v-if=\"n === 'gap'\" class=\"e-page-gap\" aria-hidden=\"true\">&hellip;</span>\n <button\n v-else\n type=\"button\"\n class=\"e-page\"\n :aria-current=\"n === page ? 'page' : undefined\"\n :aria-label=\"t('pageN', { n })\"\n @click=\"page = n\"\n >\n {{ n }}\n </button>\n </li>\n </ul>\n <EButton variant=\"outline\" :disabled=\"page >= pageCount\" @click=\"page = page + 1\">\n {{ t(\"next\") }}\n <EIcon name=\"chevron-right\" />\n </EButton>\n </nav>\n</template>\n\n<style>\n@layer e.composites {\n .e-pager {\n display: flex;\n flex-wrap: wrap;\n align-items: center;\n justify-content: center;\n gap: var(--e-space-3);\n }\n\n .e-pages {\n display: flex;\n align-items: center;\n gap: var(--e-space-1);\n margin: 0;\n padding: 0;\n list-style: none;\n }\n\n .e-page {\n display: inline-grid;\n place-items: center;\n min-width: var(--e-control-height);\n height: var(--e-control-height);\n padding: 0 var(--e-space-2);\n border: 0;\n border-radius: var(--e-radius-md);\n background: transparent;\n color: var(--e-ink);\n font: 500 var(--e-text-sm)/1 var(--e-font-mono);\n font-variant-numeric: tabular-nums;\n cursor: pointer;\n transition:\n background-color var(--e-duration-tap) var(--e-easing-out),\n box-shadow var(--e-duration-tap) var(--e-easing-out);\n }\n\n .e-page:hover {\n background: var(--e-surface-hover);\n box-shadow: inset 0 0 0 var(--e-stroke-edge) var(--e-border-strong);\n }\n\n .e-page:focus-visible {\n outline: var(--e-stroke-focus) solid var(--e-focus-ring);\n outline-offset: var(--e-focus-gap);\n }\n\n .e-page[aria-current=\"page\"] {\n background: var(--e-primary);\n box-shadow: none;\n color: var(--e-on-primary);\n font-weight: 600;\n cursor: default;\n }\n\n .e-page-gap {\n display: inline-grid;\n place-items: center;\n min-width: calc(var(--e-space-6) + var(--e-space-1));\n color: var(--e-muted);\n }\n\n @media (max-width: 32rem) {\n .e-pages {\n display: none;\n }\n\n .e-pager {\n justify-content: space-between;\n }\n }\n\n @media (prefers-reduced-motion: reduce) {\n .e-page {\n transition: none;\n }\n }\n\n @media (forced-colors: active) {\n .e-page[aria-current=\"page\"] {\n forced-color-adjust: none;\n background: Highlight;\n color: HighlightText;\n }\n }\n\n @media print {\n .e-pager {\n display: none;\n }\n }\n}\n</style>\n"],"mappings":""}
@@ -1 +1 @@
1
- {"version":3,"file":"EPagination.vue_vue_type_script_setup_true_lang.js","names":["_useModel","_openBlock","_createElementBlock","_unref","_createVNode","EButton","_withCtx","_createTextVNode","_toDisplayString","_createElementVNode","_Fragment","_renderList","EIcon","EIcon_default","EButton_default","_hoisted_1","_hoisted_2","_hoisted_3","_hoisted_4","EPagination_vue_vue_type_script_setup_true_lang_default","\"modelValue\"","\"modelModifiers\"","props","__props","page","useModel","t","useMessages","items","computed","list","i","before","k","after","n","openBlock","createElementBlock","unref","createVNode","_cache","withCtx","createTextVNode","toDisplayString","createElementVNode","Fragment","renderList"],"sources":["../../../src/components/Pagination/EPagination.vue"],"sourcesContent":["<script setup lang=\"ts\">\nimport { computed } from \"vue\";\nimport EButton from \"../Button/EButton.vue\";\nimport EIcon from \"../Icon/EIcon.vue\";\nimport { useMessages } from \"../../config.js\";\nimport \"../../styles/base.css\";\n\nconst props = defineProps<{\n /** How many pages there are. */\n pageCount: number;\n}>();\n\n/** The current page, from 1. */\nconst page = defineModel<number>({ default: 1 });\n\nconst t = useMessages();\n\nconst items = computed<(number | \"gap\")[]>(() => {\n const list: (number | \"gap\")[] = [];\n for (let i = 1; i <= props.pageCount; i++) {\n if (i === 1 || i === props.pageCount || Math.abs(i - page.value) <= 1) list.push(i);\n else if (list[list.length - 1] !== \"gap\") list.push(\"gap\");\n }\n return list.map((n, k) => {\n const before = list[k - 1];\n const after = list[k + 1];\n return n === \"gap\" && typeof before === \"number\" && typeof after === \"number\" && after - before === 2\n ? before + 1\n : n;\n });\n});\n</script>\n\n<template>\n <nav class=\"e-pager\" :aria-label=\"t('pagination')\">\n <EButton variant=\"outline\" icon=\"chevron-left\" :disabled=\"page <= 1\" @click=\"page = page - 1\">\n {{ t(\"previous\") }}\n </EButton>\n <ul class=\"e-pages\">\n <li v-for=\"(n, i) in items\" :key=\"i\">\n <span v-if=\"n === 'gap'\" class=\"e-page-gap\" aria-hidden=\"true\">&hellip;</span>\n <button\n v-else\n type=\"button\"\n class=\"e-page\"\n :aria-current=\"n === page ? 'page' : undefined\"\n :aria-label=\"t('pageN', { n })\"\n @click=\"page = n\"\n >\n {{ n }}\n </button>\n </li>\n </ul>\n <EButton variant=\"outline\" :disabled=\"page >= pageCount\" @click=\"page = page + 1\">\n {{ t(\"next\") }}\n <EIcon name=\"chevron-right\" />\n </EButton>\n </nav>\n</template>\n\n<style>\n@layer e.composites {\n .e-pager {\n display: flex;\n flex-wrap: wrap;\n align-items: center;\n justify-content: center;\n gap: var(--e-space-3);\n }\n\n .e-pages {\n display: flex;\n align-items: center;\n gap: var(--e-space-1);\n margin: 0;\n padding: 0;\n list-style: none;\n }\n\n .e-page {\n display: inline-grid;\n place-items: center;\n min-width: var(--e-control-height);\n height: var(--e-control-height);\n padding: 0 var(--e-space-2);\n border: var(--e-stroke-edge) solid transparent;\n border-radius: var(--e-radius-md);\n background: transparent;\n color: var(--e-ink);\n font: 500 var(--e-text-sm)/1 var(--e-font-mono);\n font-variant-numeric: tabular-nums;\n cursor: pointer;\n transition:\n background-color var(--e-duration-tap) var(--e-easing-out),\n border-color var(--e-duration-tap) var(--e-easing-out);\n }\n\n .e-page:hover {\n background: var(--e-surface-hover);\n border-color: var(--e-border-strong);\n\n }\n\n .e-page:focus-visible {\n outline: var(--e-stroke-focus) solid var(--e-focus-ring);\n outline-offset: var(--e-focus-gap);\n }\n\n .e-page[aria-current=\"page\"] {\n background: var(--e-primary);\n border-color: var(--e-primary);\n color: var(--e-on-primary);\n font-weight: 600;\n cursor: default;\n }\n\n .e-page-gap {\n display: inline-grid;\n place-items: center;\n min-width: calc(var(--e-space-6) + var(--e-space-1));\n color: var(--e-muted);\n }\n\n @media (max-width: 32rem) {\n .e-pages {\n display: none;\n }\n\n .e-pager {\n justify-content: space-between;\n }\n }\n\n @media (prefers-reduced-motion: reduce) {\n .e-page {\n transition: none;\n }\n }\n\n @media (forced-colors: active) {\n .e-page[aria-current=\"page\"] {\n forced-color-adjust: none;\n background: Highlight;\n color: HighlightText;\n }\n }\n\n @media print {\n .e-pager {\n display: none;\n }\n }\n}\n</style>\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;EAOA,IAAMsB,IAAQC,GAMRC,IAAOxB,EAAmBuB,GAAA,YAAe,GAEzCG,IAAIC,EAAY,GAEhBC,IAAQC,QAAmC;GAC/C,IAAMC,IAA2B,CAAC;GAClC,KAAK,IAAIC,IAAI,GAAGA,KAAKT,EAAM,WAAW,KACpC,AAAIS,MAAM,KAAKA,MAAMT,EAAM,aAAa,KAAK,IAAIS,IAAIP,EAAK,KAAK,KAAK,IAAGM,EAAK,KAAKC,CAAC,IACzED,EAAKA,EAAK,SAAS,OAAO,SAAOA,EAAK,KAAK,KAAK;GAE3D,OAAOA,EAAK,KAAK,GAAG,MAAM;IACxB,IAAME,IAASF,EAAKG,IAAI,IAClBC,IAAQJ,EAAKG,IAAI;IACvB,OAAOE,MAAM,SAAS,OAAOH,KAAW,YAAY,OAAOE,KAAU,YAAYA,IAAQF,MAAW,IAChGA,IAAS,IACTG;GACN,CAAC;EACH,CAAC;E,kBAIClC,EAAA,GAAAC,EAuBM,OAAA;GAvBD,OAAM;GAAW,cAAYC,EAAAuB,CAAA,CAAC,CAAA,YAAA;;GACjCtB,EAEUC,GAAA;IAFD,SAAQ;IAAU,MAAK;IAAgB,UAAUmB,EAAA,SAAI;IAAQ,SAAK,AAAAgB,EAAA,QAAA,MAAE,IAAA;;IAC3E,SAAAlC,QAAmB,CAAhBC,EAAAC,EAAAL,EAAAuB,CAAA,CAAC,CAAA,UAAA,CAAA,GAAA,CAAA,C;;;GAENjB,EAcK,MAdLO,GAcK,EAbHf,EAAA,EAAA,GAAAC,EAYKQ,GAAA,MAAAC,EAZgBiB,EAAA,QAAT,GAAG,OAAf3B,EAAA,GAAAC,EAYK,MAAA,EAZwB,KAAK6B,EAAC,GAAA,CACrBI,MAAC,SAAblC,EAAA,GAAAC,EAA8E,QAA9Ee,GAA+D,GAAQ,MACvEhB,EAAA,GAAAC,EASS,UAAA;;IAPP,MAAK;IACL,OAAM;IACL,gBAAciC,MAAMX,EAAA,QAAI,SAAY,KAAA;IACpC,cAAYrB,EAAAuB,CAAA,CAAC,CAAA,SAAA,EAAY,KAAC,CAAA;IAC1B,UAAK,MAAE,EAAA,QAAOS;GAEZ,GAAA3B,EAAA2B,CAAC,GAAA,GAAAjB,CAAA,E;GAIVd,EAGUC,GAAA;IAHD,SAAQ;IAAW,UAAUmB,EAAA,SAAQD,EAAA;IAAY,SAAK,AAAAiB,EAAA,QAAA,MAAE,EAAA,SAAW;;IAC1E,SAAAlC,QAAe,CAAZC,EAAAC,EAAAL,EAAAuB,CAAA,CAAC,CAAA,MAAA,CAAA,IAAW,KACf,CAAA,GAAAtB,EAA8BQ,GAAA,EAAvB,MAAK,gBAAe,CAAA,C"}
1
+ {"version":3,"file":"EPagination.vue_vue_type_script_setup_true_lang.js","names":["_useModel","_openBlock","_createElementBlock","_unref","_createVNode","EButton","_withCtx","_createTextVNode","_toDisplayString","_createElementVNode","_Fragment","_renderList","EIcon","EIcon_default","EButton_default","_hoisted_1","_hoisted_2","_hoisted_3","_hoisted_4","EPagination_vue_vue_type_script_setup_true_lang_default","\"modelValue\"","\"modelModifiers\"","props","__props","page","useModel","t","useMessages","items","computed","list","i","before","k","after","n","openBlock","createElementBlock","unref","createVNode","_cache","withCtx","createTextVNode","toDisplayString","createElementVNode","Fragment","renderList"],"sources":["../../../src/components/Pagination/EPagination.vue"],"sourcesContent":["<script setup lang=\"ts\">\nimport { computed } from \"vue\";\nimport EButton from \"../Button/EButton.vue\";\nimport EIcon from \"../Icon/EIcon.vue\";\nimport { useMessages } from \"../../config.js\";\nimport \"../../styles/base.css\";\n\nconst props = defineProps<{\n /** How many pages there are. */\n pageCount: number;\n}>();\n\n/** The current page, from 1. */\nconst page = defineModel<number>({ default: 1 });\n\nconst t = useMessages();\n\nconst items = computed<(number | \"gap\")[]>(() => {\n const list: (number | \"gap\")[] = [];\n for (let i = 1; i <= props.pageCount; i++) {\n if (i === 1 || i === props.pageCount || Math.abs(i - page.value) <= 1) list.push(i);\n else if (list[list.length - 1] !== \"gap\") list.push(\"gap\");\n }\n return list.map((n, k) => {\n const before = list[k - 1];\n const after = list[k + 1];\n return n === \"gap\" && typeof before === \"number\" && typeof after === \"number\" && after - before === 2\n ? before + 1\n : n;\n });\n});\n</script>\n\n<template>\n <nav class=\"e-pager\" :aria-label=\"t('pagination')\">\n <EButton variant=\"outline\" icon=\"chevron-left\" :disabled=\"page <= 1\" @click=\"page = page - 1\">\n {{ t(\"previous\") }}\n </EButton>\n <ul class=\"e-pages\">\n <li v-for=\"(n, i) in items\" :key=\"i\">\n <span v-if=\"n === 'gap'\" class=\"e-page-gap\" aria-hidden=\"true\">&hellip;</span>\n <button\n v-else\n type=\"button\"\n class=\"e-page\"\n :aria-current=\"n === page ? 'page' : undefined\"\n :aria-label=\"t('pageN', { n })\"\n @click=\"page = n\"\n >\n {{ n }}\n </button>\n </li>\n </ul>\n <EButton variant=\"outline\" :disabled=\"page >= pageCount\" @click=\"page = page + 1\">\n {{ t(\"next\") }}\n <EIcon name=\"chevron-right\" />\n </EButton>\n </nav>\n</template>\n\n<style>\n@layer e.composites {\n .e-pager {\n display: flex;\n flex-wrap: wrap;\n align-items: center;\n justify-content: center;\n gap: var(--e-space-3);\n }\n\n .e-pages {\n display: flex;\n align-items: center;\n gap: var(--e-space-1);\n margin: 0;\n padding: 0;\n list-style: none;\n }\n\n .e-page {\n display: inline-grid;\n place-items: center;\n min-width: var(--e-control-height);\n height: var(--e-control-height);\n padding: 0 var(--e-space-2);\n border: 0;\n border-radius: var(--e-radius-md);\n background: transparent;\n color: var(--e-ink);\n font: 500 var(--e-text-sm)/1 var(--e-font-mono);\n font-variant-numeric: tabular-nums;\n cursor: pointer;\n transition:\n background-color var(--e-duration-tap) var(--e-easing-out),\n box-shadow var(--e-duration-tap) var(--e-easing-out);\n }\n\n .e-page:hover {\n background: var(--e-surface-hover);\n box-shadow: inset 0 0 0 var(--e-stroke-edge) var(--e-border-strong);\n }\n\n .e-page:focus-visible {\n outline: var(--e-stroke-focus) solid var(--e-focus-ring);\n outline-offset: var(--e-focus-gap);\n }\n\n .e-page[aria-current=\"page\"] {\n background: var(--e-primary);\n box-shadow: none;\n color: var(--e-on-primary);\n font-weight: 600;\n cursor: default;\n }\n\n .e-page-gap {\n display: inline-grid;\n place-items: center;\n min-width: calc(var(--e-space-6) + var(--e-space-1));\n color: var(--e-muted);\n }\n\n @media (max-width: 32rem) {\n .e-pages {\n display: none;\n }\n\n .e-pager {\n justify-content: space-between;\n }\n }\n\n @media (prefers-reduced-motion: reduce) {\n .e-page {\n transition: none;\n }\n }\n\n @media (forced-colors: active) {\n .e-page[aria-current=\"page\"] {\n forced-color-adjust: none;\n background: Highlight;\n color: HighlightText;\n }\n }\n\n @media print {\n .e-pager {\n display: none;\n }\n }\n}\n</style>\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;EAOA,IAAMsB,IAAQC,GAMRC,IAAOxB,EAAmBuB,GAAA,YAAe,GAEzCG,IAAIC,EAAY,GAEhBC,IAAQC,QAAmC;GAC/C,IAAMC,IAA2B,CAAC;GAClC,KAAK,IAAIC,IAAI,GAAGA,KAAKT,EAAM,WAAW,KACpC,AAAIS,MAAM,KAAKA,MAAMT,EAAM,aAAa,KAAK,IAAIS,IAAIP,EAAK,KAAK,KAAK,IAAGM,EAAK,KAAKC,CAAC,IACzED,EAAKA,EAAK,SAAS,OAAO,SAAOA,EAAK,KAAK,KAAK;GAE3D,OAAOA,EAAK,KAAK,GAAG,MAAM;IACxB,IAAME,IAASF,EAAKG,IAAI,IAClBC,IAAQJ,EAAKG,IAAI;IACvB,OAAOE,MAAM,SAAS,OAAOH,KAAW,YAAY,OAAOE,KAAU,YAAYA,IAAQF,MAAW,IAChGA,IAAS,IACTG;GACN,CAAC;EACH,CAAC;E,kBAIClC,EAAA,GAAAC,EAuBM,OAAA;GAvBD,OAAM;GAAW,cAAYC,EAAAuB,CAAA,CAAC,CAAA,YAAA;;GACjCtB,EAEUC,GAAA;IAFD,SAAQ;IAAU,MAAK;IAAgB,UAAUmB,EAAA,SAAI;IAAQ,SAAK,AAAAgB,EAAA,QAAA,MAAE,IAAA;;IAC3E,SAAAlC,QAAmB,CAAhBC,EAAAC,EAAAL,EAAAuB,CAAA,CAAC,CAAA,UAAA,CAAA,GAAA,CAAA,C;;;GAENjB,EAcK,MAdLO,GAcK,EAbHf,EAAA,EAAA,GAAAC,EAYKQ,GAAA,MAAAC,EAZgBiB,EAAA,QAAT,GAAG,OAAf3B,EAAA,GAAAC,EAYK,MAAA,EAZwB,KAAK6B,EAAC,GAAA,CACrBI,MAAC,SAAblC,EAAA,GAAAC,EAA8E,QAA9Ee,GAA+D,GAAQ,MACvEhB,EAAA,GAAAC,EASS,UAAA;;IAPP,MAAK;IACL,OAAM;IACL,gBAAciC,MAAMX,EAAA,QAAI,SAAY,KAAA;IACpC,cAAYrB,EAAAuB,CAAA,CAAC,CAAA,SAAA,EAAY,KAAC,CAAA;IAC1B,UAAK,MAAE,EAAA,QAAOS;GAEZ,GAAA3B,EAAA2B,CAAC,GAAA,GAAAjB,CAAA,E;GAIVd,EAGUC,GAAA;IAHD,SAAQ;IAAW,UAAUmB,EAAA,SAAQD,EAAA;IAAY,SAAK,AAAAiB,EAAA,QAAA,MAAE,EAAA,SAAW;;IAC1E,SAAAlC,QAAe,CAAZC,EAAAC,EAAAL,EAAAuB,CAAA,CAAC,CAAA,MAAA,CAAA,IAAW,KACf,CAAA,GAAAtB,EAA8BQ,GAAA,EAAvB,MAAK,gBAAe,CAAA,C"}
@@ -1 +1 @@
1
- {"version":3,"file":"EPasswordField.js","names":["_sfc_main","EPasswordField_vue_vue_type_script_setup_true_lang_default","EPasswordField_default"],"sources":["../../../src/components/PasswordField/EPasswordField.vue"],"sourcesContent":["<script lang=\"ts\">\nexport interface PasswordRule {\n /** What the password needs, such as \"At least 10 characters\". */\n label: string;\n /** Whether the password meets the rule. */\n test: (value: string) => boolean;\n}\n</script>\n\n<script setup lang=\"ts\">\nimport { computed, ref } from \"vue\";\nimport EIcon from \"../Icon/EIcon.vue\";\nimport EField from \"../Field/EField.vue\";\nimport { useMessages } from \"../../config.js\";\nimport { focusInside } from \"../../composables/focusInside.js\";\nimport { useFieldAttrs } from \"../../composables/useFieldAttrs.js\";\nimport \"../../styles/base.css\";\nimport \"../TextField/input.css\";\nimport \"../Combobox/combo.css\";\n\ndefineOptions({ inheritAttrs: false });\n\nconst props = defineProps<{\n /** The visible label, a mono kicker above the field. @default \"Password\" */\n label?: string;\n /** Keep the label for screen readers and remove it from the page. */\n hideLabel?: boolean;\n /** `current` for signing in, `new` for choosing one. Sets `autocomplete` (`current-password` or `new-password`) so a password manager can fill or suggest. */\n mode?: \"current\" | \"new\";\n /** `{ label, test(value) }`. A checklist under the field that updates as the person types. Each rule shows a tick or an empty circle and says \"met\" or \"not met yet\". */\n rules?: PasswordRule[];\n /** Help that stays under the field. */\n hint?: string;\n /** What to fix. Replaces the hint, marks the input invalid and is announced. */\n error?: string;\n /** The `required` attribute and a word beside the label. */\n required?: boolean;\n /** A word beside the label. Flag whichever is rarer. */\n optional?: boolean;\n /** Disables the input and the toggle. */\n disabled?: boolean;\n /** The id of the input; the label points at it. @default generated */\n id?: string;\n}>();\n\n/** The password. */\nconst model = defineModel<string>({ default: \"\" });\n\nconst t = useMessages();\nconst attrs = useFieldAttrs();\nconst input = ref<HTMLInputElement | null>(null);\nconst shown = ref(false);\n\nconst list = computed(() => props.rules ?? []);\n\nfunction inputBind(field: { id: string; ariaInvalid: \"true\" | undefined; ariaDescribedby: string | undefined }) {\n const describedby = [field.ariaDescribedby, list.value.length ? `${field.id}-rules` : \"\"].filter(Boolean).join(\" \");\n return {\n id: field.id,\n class: \"e-input\",\n type: shown.value ? \"text\" : \"password\",\n value: model.value,\n disabled: props.disabled,\n required: props.required,\n autocomplete: props.mode === \"new\" ? \"new-password\" : \"current-password\",\n autocapitalize: \"none\",\n spellcheck: false,\n \"aria-invalid\": field.ariaInvalid,\n ...attrs.input(describedby || undefined),\n };\n}\n\ndefineExpose({\n input,\n focus: () => input.value?.focus(),\n});\n</script>\n\n<template>\n <EField\n v-bind=\"attrs.wrapper()\"\n :id=\"id\"\n :label=\"label || t('password')\"\n :hide-label=\"hideLabel\"\n :hint=\"hint\"\n :error=\"error\"\n :required=\"required\"\n :optional=\"optional\"\n >\n <template #default=\"field\">\n <!-- eslint-disable-next-line vuejs-accessibility/click-events-have-key-events, vuejs-accessibility/no-static-element-interactions -->\n <div\n class=\"e-input-wrap\"\n :data-invalid=\"error ? '' : undefined\"\n :data-disabled=\"disabled ? '' : undefined\"\n @click=\"focusInside\"\n >\n <input ref=\"input\" v-bind=\"inputBind(field)\" @input=\"model = ($event.target as HTMLInputElement).value\" />\n <button\n type=\"button\"\n class=\"e-combo-btn\"\n :aria-pressed=\"shown ? 'true' : 'false'\"\n :aria-label=\"shown ? t('hidePassword') : t('showPassword')\"\n :disabled=\"disabled\"\n @click=\"shown = !shown\"\n >\n <EIcon :name=\"shown ? 'eye-slash' : 'eye'\" />\n </button>\n </div>\n <ul v-if=\"list.length\" :id=\"`${field.id}-rules`\" class=\"e-rules\" :aria-label=\"t('passwordRules')\">\n <li v-for=\"r in list\" :key=\"r.label\" class=\"e-rule\" :data-met=\"r.test(model) ? '' : undefined\">\n <EIcon v-if=\"r.test(model)\" name=\"check\" small />\n <span v-else class=\"e-rule-dot\" aria-hidden=\"true\" />\n {{ r.label }}\n <span class=\"e-sr\"> ({{ t(r.test(model) ? \"ruleMet\" : \"ruleNotMet\") }})</span>\n </li>\n </ul>\n </template>\n </EField>\n</template>\n\n<style>\n@layer e.composites {\n /* The hidden-character dots keep the size of plain text so the caret matches when they are shown. */\n .e-input-wrap .e-input[type=\"password\"] {\n letter-spacing: 0.12em;\n }\n\n .e-rules {\n display: grid;\n gap: var(--e-space-1);\n margin: 0;\n padding: 0;\n list-style: none;\n font: 400 var(--e-text-sm)/1.4 var(--e-font-sans);\n }\n\n .e-rule {\n display: flex;\n align-items: center;\n gap: var(--e-space-2);\n color: var(--e-muted);\n }\n\n .e-rule[data-met] {\n color: var(--e-secondary);\n }\n\n .e-rule .e-icon {\n flex: none;\n }\n\n .e-rule-dot {\n flex: none;\n width: 14px;\n height: 14px;\n border: var(--e-stroke-edge) solid var(--e-border-strong);\n border-radius: 50%;\n }\n}\n</style>\n"],"mappings":""}
1
+ {"version":3,"file":"EPasswordField.js","names":["_sfc_main","EPasswordField_vue_vue_type_script_setup_true_lang_default","EPasswordField_default"],"sources":["../../../src/components/PasswordField/EPasswordField.vue"],"sourcesContent":["<script lang=\"ts\">\nexport interface PasswordRule {\n /** What the password needs, such as \"At least 10 characters\". */\n label: string;\n /** Whether the password meets the rule. */\n test: (value: string) => boolean;\n}\n</script>\n\n<script setup lang=\"ts\">\nimport { computed, ref } from \"vue\";\nimport EIcon from \"../Icon/EIcon.vue\";\nimport EField from \"../Field/EField.vue\";\nimport { useMessages } from \"../../config.js\";\nimport { focusInside } from \"../../composables/focusInside.js\";\nimport { useFieldAttrs } from \"../../composables/useFieldAttrs.js\";\nimport \"../../styles/base.css\";\nimport \"../TextField/input.css\";\nimport \"../Combobox/combo.css\";\n\ndefineOptions({ inheritAttrs: false });\n\nconst props = defineProps<{\n /** The visible label, a mono kicker above the field. @default \"Password\" */\n label?: string;\n /** Keep the label for screen readers and remove it from the page. */\n hideLabel?: boolean;\n /** `current` for signing in, `new` for choosing one. Sets `autocomplete` (`current-password` or `new-password`) so a password manager can fill or suggest. */\n mode?: \"current\" | \"new\";\n /** `{ label, test(value) }`. A checklist under the field that updates as the person types. Each rule shows a tick or an empty circle and says \"met\" or \"not met yet\". */\n rules?: PasswordRule[];\n /** Help that stays under the field. */\n hint?: string;\n /** What to fix. Replaces the hint, marks the input invalid and is announced. */\n error?: string;\n /** The `required` attribute and a word beside the label. */\n required?: boolean;\n /** A word beside the label. Flag whichever is rarer. */\n optional?: boolean;\n /** Disables the input and the toggle. */\n disabled?: boolean;\n /** The id of the input; the label points at it. @default generated */\n id?: string;\n}>();\n\n/** The password. */\nconst model = defineModel<string>({ default: \"\" });\n\nconst t = useMessages();\nconst attrs = useFieldAttrs();\nconst input = ref<HTMLInputElement | null>(null);\nconst shown = ref(false);\n\nconst list = computed(() => props.rules ?? []);\n\nfunction inputBind(field: { id: string; ariaInvalid: \"true\" | undefined; ariaDescribedby: string | undefined }) {\n const describedby = [field.ariaDescribedby, list.value.length ? `${field.id}-rules` : \"\"].filter(Boolean).join(\" \");\n return {\n id: field.id,\n class: \"e-input\",\n type: shown.value ? \"text\" : \"password\",\n value: model.value,\n disabled: props.disabled,\n required: props.required,\n autocomplete: props.mode === \"new\" ? \"new-password\" : \"current-password\",\n autocapitalize: \"none\",\n spellcheck: false,\n \"aria-invalid\": field.ariaInvalid,\n ...attrs.input(describedby || undefined),\n };\n}\n\ndefineExpose({\n input,\n focus: () => input.value?.focus(),\n});\n</script>\n\n<template>\n <EField\n v-bind=\"attrs.wrapper()\"\n :id=\"id\"\n :label=\"label || t('password')\"\n :hide-label=\"hideLabel\"\n :hint=\"hint\"\n :error=\"error\"\n :required=\"required\"\n :optional=\"optional\"\n >\n <template #default=\"field\">\n <!-- eslint-disable-next-line vuejs-accessibility/click-events-have-key-events, vuejs-accessibility/no-static-element-interactions -->\n <div\n class=\"e-input-wrap\"\n :data-invalid=\"error ? '' : undefined\"\n :data-disabled=\"disabled ? '' : undefined\"\n @click=\"focusInside\"\n >\n <input ref=\"input\" v-bind=\"inputBind(field)\" @input=\"model = ($event.target as HTMLInputElement).value\" />\n <button\n type=\"button\"\n class=\"e-combo-btn\"\n :aria-pressed=\"shown ? 'true' : 'false'\"\n :aria-label=\"shown ? t('hidePassword') : t('showPassword')\"\n :disabled=\"disabled\"\n @click=\"shown = !shown\"\n >\n <EIcon :name=\"shown ? 'eye-slash' : 'eye'\" />\n </button>\n </div>\n <ul v-if=\"list.length\" :id=\"`${field.id}-rules`\" class=\"e-rules\" :aria-label=\"t('passwordRules')\">\n <li v-for=\"r in list\" :key=\"r.label\" class=\"e-rule\" :data-met=\"r.test(model) ? '' : undefined\">\n <EIcon v-if=\"r.test(model)\" name=\"check\" small />\n <span v-else class=\"e-rule-dot\" aria-hidden=\"true\" />\n {{ r.label }}\n <span class=\"e-sr\"> ({{ t(r.test(model) ? \"ruleMet\" : \"ruleNotMet\") }})</span>\n </li>\n </ul>\n </template>\n </EField>\n</template>\n\n<style>\n@layer e.composites {\n /* The hidden-character dots keep the size of plain text so the caret matches when they are shown. */\n .e-input-wrap .e-input[type=\"password\"] {\n letter-spacing: 0.12em;\n }\n\n .e-rules {\n display: grid;\n gap: var(--e-space-1);\n margin: 0;\n padding: 0;\n list-style: none;\n font: 400 var(--e-text-sm)/1.4 var(--e-font-sans);\n }\n\n .e-rule {\n display: flex;\n align-items: center;\n gap: var(--e-space-2);\n color: var(--e-muted);\n }\n\n .e-rule[data-met] {\n color: var(--e-secondary);\n }\n\n .e-rule .e-icon {\n flex: none;\n }\n\n .e-rule-dot {\n flex: none;\n width: 14px;\n height: 14px;\n border-radius: 50%;\n box-shadow: inset 0 0 0 var(--e-stroke-edge) var(--e-border-strong);\n }\n}\n</style>\n"],"mappings":""}
@@ -1 +1 @@
1
- {"version":3,"file":"EPasswordField.vue_vue_type_script_setup_true_lang.js","names":["_useModel","_openBlock","_createBlock","EField","_mergeProps","_unref","_withCtx","_createElementVNode","_createVNode","EIcon","_createElementBlock","_Fragment","_renderList","_createTextVNode","_toDisplayString","_createCommentVNode","EIcon_default","EField_default","_hoisted_1","_hoisted_2","_hoisted_3","_hoisted_4","_hoisted_5","_hoisted_6","EPasswordField_vue_vue_type_script_setup_true_lang_default","\"modelValue\"","\"modelModifiers\"","__expose","props","__props","model","useModel","t","useMessages","attrs","useFieldAttrs","input","ref","shown","list","computed","inputBind","describedby","field","openBlock","createBlock","mergeProps","unref","withCtx","createElementVNode","_cache","args","focusInside","$event","createVNode","createElementBlock","Fragment","renderList","r","createTextVNode","toDisplayString","createCommentVNode"],"sources":["../../../src/components/PasswordField/EPasswordField.vue"],"sourcesContent":["<script lang=\"ts\">\nexport interface PasswordRule {\n /** What the password needs, such as \"At least 10 characters\". */\n label: string;\n /** Whether the password meets the rule. */\n test: (value: string) => boolean;\n}\n</script>\n\n<script setup lang=\"ts\">\nimport { computed, ref } from \"vue\";\nimport EIcon from \"../Icon/EIcon.vue\";\nimport EField from \"../Field/EField.vue\";\nimport { useMessages } from \"../../config.js\";\nimport { focusInside } from \"../../composables/focusInside.js\";\nimport { useFieldAttrs } from \"../../composables/useFieldAttrs.js\";\nimport \"../../styles/base.css\";\nimport \"../TextField/input.css\";\nimport \"../Combobox/combo.css\";\n\ndefineOptions({ inheritAttrs: false });\n\nconst props = defineProps<{\n /** The visible label, a mono kicker above the field. @default \"Password\" */\n label?: string;\n /** Keep the label for screen readers and remove it from the page. */\n hideLabel?: boolean;\n /** `current` for signing in, `new` for choosing one. Sets `autocomplete` (`current-password` or `new-password`) so a password manager can fill or suggest. */\n mode?: \"current\" | \"new\";\n /** `{ label, test(value) }`. A checklist under the field that updates as the person types. Each rule shows a tick or an empty circle and says \"met\" or \"not met yet\". */\n rules?: PasswordRule[];\n /** Help that stays under the field. */\n hint?: string;\n /** What to fix. Replaces the hint, marks the input invalid and is announced. */\n error?: string;\n /** The `required` attribute and a word beside the label. */\n required?: boolean;\n /** A word beside the label. Flag whichever is rarer. */\n optional?: boolean;\n /** Disables the input and the toggle. */\n disabled?: boolean;\n /** The id of the input; the label points at it. @default generated */\n id?: string;\n}>();\n\n/** The password. */\nconst model = defineModel<string>({ default: \"\" });\n\nconst t = useMessages();\nconst attrs = useFieldAttrs();\nconst input = ref<HTMLInputElement | null>(null);\nconst shown = ref(false);\n\nconst list = computed(() => props.rules ?? []);\n\nfunction inputBind(field: { id: string; ariaInvalid: \"true\" | undefined; ariaDescribedby: string | undefined }) {\n const describedby = [field.ariaDescribedby, list.value.length ? `${field.id}-rules` : \"\"].filter(Boolean).join(\" \");\n return {\n id: field.id,\n class: \"e-input\",\n type: shown.value ? \"text\" : \"password\",\n value: model.value,\n disabled: props.disabled,\n required: props.required,\n autocomplete: props.mode === \"new\" ? \"new-password\" : \"current-password\",\n autocapitalize: \"none\",\n spellcheck: false,\n \"aria-invalid\": field.ariaInvalid,\n ...attrs.input(describedby || undefined),\n };\n}\n\ndefineExpose({\n input,\n focus: () => input.value?.focus(),\n});\n</script>\n\n<template>\n <EField\n v-bind=\"attrs.wrapper()\"\n :id=\"id\"\n :label=\"label || t('password')\"\n :hide-label=\"hideLabel\"\n :hint=\"hint\"\n :error=\"error\"\n :required=\"required\"\n :optional=\"optional\"\n >\n <template #default=\"field\">\n <!-- eslint-disable-next-line vuejs-accessibility/click-events-have-key-events, vuejs-accessibility/no-static-element-interactions -->\n <div\n class=\"e-input-wrap\"\n :data-invalid=\"error ? '' : undefined\"\n :data-disabled=\"disabled ? '' : undefined\"\n @click=\"focusInside\"\n >\n <input ref=\"input\" v-bind=\"inputBind(field)\" @input=\"model = ($event.target as HTMLInputElement).value\" />\n <button\n type=\"button\"\n class=\"e-combo-btn\"\n :aria-pressed=\"shown ? 'true' : 'false'\"\n :aria-label=\"shown ? t('hidePassword') : t('showPassword')\"\n :disabled=\"disabled\"\n @click=\"shown = !shown\"\n >\n <EIcon :name=\"shown ? 'eye-slash' : 'eye'\" />\n </button>\n </div>\n <ul v-if=\"list.length\" :id=\"`${field.id}-rules`\" class=\"e-rules\" :aria-label=\"t('passwordRules')\">\n <li v-for=\"r in list\" :key=\"r.label\" class=\"e-rule\" :data-met=\"r.test(model) ? '' : undefined\">\n <EIcon v-if=\"r.test(model)\" name=\"check\" small />\n <span v-else class=\"e-rule-dot\" aria-hidden=\"true\" />\n {{ r.label }}\n <span class=\"e-sr\"> ({{ t(r.test(model) ? \"ruleMet\" : \"ruleNotMet\") }})</span>\n </li>\n </ul>\n </template>\n </EField>\n</template>\n\n<style>\n@layer e.composites {\n /* The hidden-character dots keep the size of plain text so the caret matches when they are shown. */\n .e-input-wrap .e-input[type=\"password\"] {\n letter-spacing: 0.12em;\n }\n\n .e-rules {\n display: grid;\n gap: var(--e-space-1);\n margin: 0;\n padding: 0;\n list-style: none;\n font: 400 var(--e-text-sm)/1.4 var(--e-font-sans);\n }\n\n .e-rule {\n display: flex;\n align-items: center;\n gap: var(--e-space-2);\n color: var(--e-muted);\n }\n\n .e-rule[data-met] {\n color: var(--e-secondary);\n }\n\n .e-rule .e-icon {\n flex: none;\n }\n\n .e-rule-dot {\n flex: none;\n width: 14px;\n height: 14px;\n border: var(--e-stroke-edge) solid var(--e-border-strong);\n border-radius: 50%;\n }\n}\n</style>\n"],"mappings":"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"}
1
+ {"version":3,"file":"EPasswordField.vue_vue_type_script_setup_true_lang.js","names":["_useModel","_openBlock","_createBlock","EField","_mergeProps","_unref","_withCtx","_createElementVNode","_createVNode","EIcon","_createElementBlock","_Fragment","_renderList","_createTextVNode","_toDisplayString","_createCommentVNode","EIcon_default","EField_default","_hoisted_1","_hoisted_2","_hoisted_3","_hoisted_4","_hoisted_5","_hoisted_6","EPasswordField_vue_vue_type_script_setup_true_lang_default","\"modelValue\"","\"modelModifiers\"","__expose","props","__props","model","useModel","t","useMessages","attrs","useFieldAttrs","input","ref","shown","list","computed","inputBind","describedby","field","openBlock","createBlock","mergeProps","unref","withCtx","createElementVNode","_cache","args","focusInside","$event","createVNode","createElementBlock","Fragment","renderList","r","createTextVNode","toDisplayString","createCommentVNode"],"sources":["../../../src/components/PasswordField/EPasswordField.vue"],"sourcesContent":["<script lang=\"ts\">\nexport interface PasswordRule {\n /** What the password needs, such as \"At least 10 characters\". */\n label: string;\n /** Whether the password meets the rule. */\n test: (value: string) => boolean;\n}\n</script>\n\n<script setup lang=\"ts\">\nimport { computed, ref } from \"vue\";\nimport EIcon from \"../Icon/EIcon.vue\";\nimport EField from \"../Field/EField.vue\";\nimport { useMessages } from \"../../config.js\";\nimport { focusInside } from \"../../composables/focusInside.js\";\nimport { useFieldAttrs } from \"../../composables/useFieldAttrs.js\";\nimport \"../../styles/base.css\";\nimport \"../TextField/input.css\";\nimport \"../Combobox/combo.css\";\n\ndefineOptions({ inheritAttrs: false });\n\nconst props = defineProps<{\n /** The visible label, a mono kicker above the field. @default \"Password\" */\n label?: string;\n /** Keep the label for screen readers and remove it from the page. */\n hideLabel?: boolean;\n /** `current` for signing in, `new` for choosing one. Sets `autocomplete` (`current-password` or `new-password`) so a password manager can fill or suggest. */\n mode?: \"current\" | \"new\";\n /** `{ label, test(value) }`. A checklist under the field that updates as the person types. Each rule shows a tick or an empty circle and says \"met\" or \"not met yet\". */\n rules?: PasswordRule[];\n /** Help that stays under the field. */\n hint?: string;\n /** What to fix. Replaces the hint, marks the input invalid and is announced. */\n error?: string;\n /** The `required` attribute and a word beside the label. */\n required?: boolean;\n /** A word beside the label. Flag whichever is rarer. */\n optional?: boolean;\n /** Disables the input and the toggle. */\n disabled?: boolean;\n /** The id of the input; the label points at it. @default generated */\n id?: string;\n}>();\n\n/** The password. */\nconst model = defineModel<string>({ default: \"\" });\n\nconst t = useMessages();\nconst attrs = useFieldAttrs();\nconst input = ref<HTMLInputElement | null>(null);\nconst shown = ref(false);\n\nconst list = computed(() => props.rules ?? []);\n\nfunction inputBind(field: { id: string; ariaInvalid: \"true\" | undefined; ariaDescribedby: string | undefined }) {\n const describedby = [field.ariaDescribedby, list.value.length ? `${field.id}-rules` : \"\"].filter(Boolean).join(\" \");\n return {\n id: field.id,\n class: \"e-input\",\n type: shown.value ? \"text\" : \"password\",\n value: model.value,\n disabled: props.disabled,\n required: props.required,\n autocomplete: props.mode === \"new\" ? \"new-password\" : \"current-password\",\n autocapitalize: \"none\",\n spellcheck: false,\n \"aria-invalid\": field.ariaInvalid,\n ...attrs.input(describedby || undefined),\n };\n}\n\ndefineExpose({\n input,\n focus: () => input.value?.focus(),\n});\n</script>\n\n<template>\n <EField\n v-bind=\"attrs.wrapper()\"\n :id=\"id\"\n :label=\"label || t('password')\"\n :hide-label=\"hideLabel\"\n :hint=\"hint\"\n :error=\"error\"\n :required=\"required\"\n :optional=\"optional\"\n >\n <template #default=\"field\">\n <!-- eslint-disable-next-line vuejs-accessibility/click-events-have-key-events, vuejs-accessibility/no-static-element-interactions -->\n <div\n class=\"e-input-wrap\"\n :data-invalid=\"error ? '' : undefined\"\n :data-disabled=\"disabled ? '' : undefined\"\n @click=\"focusInside\"\n >\n <input ref=\"input\" v-bind=\"inputBind(field)\" @input=\"model = ($event.target as HTMLInputElement).value\" />\n <button\n type=\"button\"\n class=\"e-combo-btn\"\n :aria-pressed=\"shown ? 'true' : 'false'\"\n :aria-label=\"shown ? t('hidePassword') : t('showPassword')\"\n :disabled=\"disabled\"\n @click=\"shown = !shown\"\n >\n <EIcon :name=\"shown ? 'eye-slash' : 'eye'\" />\n </button>\n </div>\n <ul v-if=\"list.length\" :id=\"`${field.id}-rules`\" class=\"e-rules\" :aria-label=\"t('passwordRules')\">\n <li v-for=\"r in list\" :key=\"r.label\" class=\"e-rule\" :data-met=\"r.test(model) ? '' : undefined\">\n <EIcon v-if=\"r.test(model)\" name=\"check\" small />\n <span v-else class=\"e-rule-dot\" aria-hidden=\"true\" />\n {{ r.label }}\n <span class=\"e-sr\"> ({{ t(r.test(model) ? \"ruleMet\" : \"ruleNotMet\") }})</span>\n </li>\n </ul>\n </template>\n </EField>\n</template>\n\n<style>\n@layer e.composites {\n /* The hidden-character dots keep the size of plain text so the caret matches when they are shown. */\n .e-input-wrap .e-input[type=\"password\"] {\n letter-spacing: 0.12em;\n }\n\n .e-rules {\n display: grid;\n gap: var(--e-space-1);\n margin: 0;\n padding: 0;\n list-style: none;\n font: 400 var(--e-text-sm)/1.4 var(--e-font-sans);\n }\n\n .e-rule {\n display: flex;\n align-items: center;\n gap: var(--e-space-2);\n color: var(--e-muted);\n }\n\n .e-rule[data-met] {\n color: var(--e-secondary);\n }\n\n .e-rule .e-icon {\n flex: none;\n }\n\n .e-rule-dot {\n flex: none;\n width: 14px;\n height: 14px;\n border-radius: 50%;\n box-shadow: inset 0 0 0 var(--e-stroke-edge) var(--e-border-strong);\n }\n}\n</style>\n"],"mappings":"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"}
@@ -1 +1 @@
1
- {"version":3,"file":"ESearchBar.js","names":["_sfc_main","ESearchBar_vue_vue_type_script_setup_true_lang_default","ESearchBar_default"],"sources":["../../../src/components/SearchBar/ESearchBar.vue"],"sourcesContent":["<script setup lang=\"ts\">\nimport EIcon from \"../Icon/EIcon.vue\";\nimport EButton from \"../Button/EButton.vue\";\nimport { ref } from \"vue\";\nimport { useMessages } from \"../../config.js\";\nimport { useFieldAttrs } from \"../../composables/useFieldAttrs.js\";\nimport \"../../styles/base.css\";\nimport \"../TextField/input.css\";\n\ndefineOptions({ inheritAttrs: false });\n\nwithDefaults(\n defineProps<{\n /** Names the box and the search landmark; there is no visible label. @default \"Search\" */\n label?: string;\n /** Say what can be searched, briefly. @default \"Search\" */\n placeholder?: string;\n /** The text on the button. @default \"Search\" */\n action?: string;\n /** Leaves out the button, for a box that filters or searches as you type. Enter still submits. */\n hideAction?: boolean;\n /** The clear button, shown when there is text. On by default. */\n clearable?: boolean;\n /** The name submitted with a form. @default \"q\" */\n name?: string;\n /** Disables the box and button. Say why in an `ENotice`. */\n disabled?: boolean;\n }>(),\n { clearable: true },\n);\n\nconst emit = defineEmits<{\n /** The person pressed Enter or the button. */\n submit: [value: string];\n}>();\n\n/** The text. */\nconst model = defineModel<string>({ default: \"\" });\n\nconst t = useMessages();\nconst attrs = useFieldAttrs();\nconst box = ref<HTMLInputElement | null>(null);\n\nfunction clear() {\n model.value = \"\";\n box.value?.focus();\n}\n\ndefineExpose({\n input: box,\n focus: () => box.value?.focus(),\n});\n</script>\n\n<template>\n <form\n class=\"e-search\"\n v-bind=\"attrs.wrapper()\"\n role=\"search\"\n :aria-label=\"label || t('search')\"\n @submit.prevent=\"emit('submit', model)\"\n >\n <span class=\"e-search-lead\"><EIcon name=\"search\" /></span>\n <input\n ref=\"box\"\n v-bind=\"attrs.input()\"\n class=\"e-input\"\n :name=\"name || 'q'\"\n :aria-label=\"label || t('search')\"\n :placeholder=\"placeholder || t('search')\"\n :value=\"model\"\n :disabled=\"disabled\"\n @input=\"model = ($event.target as HTMLInputElement).value\"\n />\n <button\n v-if=\"clearable && model && !disabled\"\n type=\"button\"\n class=\"e-search-clear\"\n :aria-label=\"t('clear')\"\n @mousedown.prevent\n @click=\"clear\"\n >\n <EIcon name=\"x\" />\n </button>\n <EButton v-if=\"!hideAction\" type=\"submit\" :disabled=\"disabled\">{{ action || t(\"search\") }}</EButton>\n </form>\n</template>\n\n<style>\n@layer e.controls {\n .e-search {\n display: flex;\n align-items: center;\n gap: var(--e-space-1);\n height: var(--e-control-height);\n padding: 0 var(--e-space-1) 0 var(--e-space-2);\n border: var(--e-stroke-edge) solid var(--e-border-strong);\n border-radius: var(--e-radius-md);\n background: var(--e-surface);\n box-shadow: var(--e-well);\n transition: border-color var(--e-duration-tap) var(--e-easing-out);\n }\n\n .e-search:hover {\n border-color: var(--e-ink);\n\n }\n\n .e-search .e-btn {\n position: relative;\n height: calc(var(--e-control-height) - 6px - var(--e-lift));\n padding: 0 var(--e-space-3);\n font-size: var(--e-text-md);\n }\n\n .e-search .e-btn::after {\n content: \"\";\n position: absolute;\n inset: -3px;\n }\n\n .e-search-clear {\n display: inline-grid;\n place-items: center;\n position: relative;\n flex: none;\n width: calc(var(--e-control-height) - 9px);\n height: calc(var(--e-control-height) - 9px);\n padding: 0;\n border: 0;\n border-radius: var(--e-radius-sm);\n background: transparent;\n color: var(--e-ink);\n cursor: pointer;\n transition: background-color var(--e-duration-tap) var(--e-easing-out);\n }\n\n .e-search-clear::after {\n content: \"\";\n position: absolute;\n inset: -5px;\n }\n\n .e-search-clear:hover {\n background: var(--e-wash-hover);\n box-shadow: inset 0 0 0 var(--e-stroke-hair) var(--e-wash-ring);\n }\n\n .e-search-clear:active {\n background: var(--e-wash-press);\n box-shadow: inset 0 0 0 var(--e-stroke-edge) var(--e-ink);\n }\n\n .e-search-clear:focus-visible {\n outline: var(--e-stroke-focus) solid var(--e-focus-ring);\n outline-offset: calc(-1 * var(--e-stroke-focus));\n }\n\n .e-search-lead {\n display: grid;\n place-items: center;\n flex: none;\n width: var(--e-space-8);\n color: var(--e-muted);\n }\n\n .e-search .e-input {\n flex: 1;\n text-overflow: ellipsis;\n height: 100%;\n border: 0;\n outline: 0;\n background: transparent;\n box-shadow: none;\n font-size: var(--e-text-md);\n padding-inline: var(--e-space-2);\n }\n\n .e-search .e-input:hover,\n .e-search .e-input:focus {\n border: 0;\n background: transparent;\n }\n\n .e-search .e-input:focus-visible {\n outline: none;\n }\n\n .e-search:focus-within {\n border-color: var(--e-focus-field);\n outline: var(--e-stroke-focus) solid var(--e-focus-field);\n outline-offset: var(--e-focus-gap-field);\n }\n\n @media (prefers-reduced-motion: reduce) {\n .e-search {\n transition: none;\n }\n }\n\n @media print {\n .e-search {\n display: none;\n }\n }\n}\n</style>\n"],"mappings":""}
1
+ {"version":3,"file":"ESearchBar.js","names":["_sfc_main","ESearchBar_vue_vue_type_script_setup_true_lang_default","ESearchBar_default"],"sources":["../../../src/components/SearchBar/ESearchBar.vue"],"sourcesContent":["<script setup lang=\"ts\">\nimport EIcon from \"../Icon/EIcon.vue\";\nimport EButton from \"../Button/EButton.vue\";\nimport { ref } from \"vue\";\nimport { useMessages } from \"../../config.js\";\nimport { useFieldAttrs } from \"../../composables/useFieldAttrs.js\";\nimport \"../../styles/base.css\";\nimport \"../TextField/input.css\";\n\ndefineOptions({ inheritAttrs: false });\n\nwithDefaults(\n defineProps<{\n /** Names the box and the search landmark; there is no visible label. @default \"Search\" */\n label?: string;\n /** Say what can be searched, briefly. @default \"Search\" */\n placeholder?: string;\n /** The text on the button. @default \"Search\" */\n action?: string;\n /** Leaves out the button, for a box that filters or searches as you type. Enter still submits. */\n hideAction?: boolean;\n /** The clear button, shown when there is text. */\n clearable?: boolean;\n /** The name submitted with a form. @default \"q\" */\n name?: string;\n /** Disables the box and button. Say why in an `ENotice`. */\n disabled?: boolean;\n }>(),\n { clearable: true },\n);\n\nconst emit = defineEmits<{\n /** The person pressed Enter or the button. */\n submit: [value: string];\n}>();\n\n/** The text. */\nconst model = defineModel<string>({ default: \"\" });\n\nconst t = useMessages();\nconst attrs = useFieldAttrs();\nconst box = ref<HTMLInputElement | null>(null);\n\nfunction clear() {\n model.value = \"\";\n box.value?.focus();\n}\n\ndefineExpose({\n input: box,\n focus: () => box.value?.focus(),\n});\n</script>\n\n<template>\n <form\n class=\"e-search\"\n v-bind=\"attrs.wrapper()\"\n role=\"search\"\n :aria-label=\"label || t('search')\"\n @submit.prevent=\"emit('submit', model)\"\n >\n <span class=\"e-search-lead\"><EIcon name=\"search\" /></span>\n <input\n ref=\"box\"\n v-bind=\"attrs.input()\"\n class=\"e-input\"\n :name=\"name || 'q'\"\n :aria-label=\"label || t('search')\"\n :placeholder=\"placeholder || t('search')\"\n :value=\"model\"\n :disabled=\"disabled\"\n @input=\"model = ($event.target as HTMLInputElement).value\"\n />\n <button\n v-if=\"clearable && model && !disabled\"\n type=\"button\"\n class=\"e-search-clear\"\n :aria-label=\"t('clear')\"\n @mousedown.prevent\n @click=\"clear\"\n >\n <EIcon name=\"x\" />\n </button>\n <EButton v-if=\"!hideAction\" type=\"submit\" :disabled=\"disabled\">{{ action || t(\"search\") }}</EButton>\n </form>\n</template>\n\n<style>\n@layer e.controls {\n .e-search {\n --e-ring: var(--e-border-strong);\n\n display: flex;\n align-items: center;\n gap: var(--e-space-1);\n height: var(--e-control-height);\n padding: 0 var(--e-space-1) 0 var(--e-space-2);\n border-radius: var(--e-radius-md);\n background: var(--e-surface);\n box-shadow:\n inset 0 0 0 var(--e-stroke-edge) var(--e-ring),\n var(--e-well);\n transition: box-shadow var(--e-duration-tap) var(--e-easing-out);\n }\n\n .e-search:hover {\n background: var(--e-surface-hover);\n }\n\n .e-search .e-btn {\n position: relative;\n height: calc(var(--e-control-height) - 6px);\n padding: 0 var(--e-space-3) var(--e-lift);\n font-size: var(--e-text-md);\n }\n\n .e-search .e-btn::after {\n content: \"\";\n position: absolute;\n inset: -3px;\n }\n\n .e-search-clear {\n display: inline-grid;\n place-items: center;\n position: relative;\n flex: none;\n width: calc(var(--e-control-height) - 9px);\n height: calc(var(--e-control-height) - 9px);\n padding: 0;\n border: 0;\n border-radius: var(--e-radius-sm);\n background: transparent;\n color: var(--e-ink);\n cursor: pointer;\n transition: background-color var(--e-duration-tap) var(--e-easing-out);\n }\n\n .e-search-clear::after {\n content: \"\";\n position: absolute;\n inset: -5px;\n }\n\n .e-search-clear:hover {\n background: var(--e-wash-hover);\n box-shadow: inset 0 0 0 var(--e-stroke-hair) var(--e-wash-ring);\n }\n\n .e-search-clear:active {\n background: var(--e-wash-press);\n box-shadow: inset 0 0 0 var(--e-stroke-edge) var(--e-ink);\n }\n\n .e-search-clear:focus-visible {\n outline: var(--e-stroke-focus) solid var(--e-focus-ring);\n outline-offset: calc(-1 * var(--e-stroke-focus));\n }\n\n .e-search-lead {\n display: grid;\n place-items: center;\n flex: none;\n width: var(--e-space-8);\n color: var(--e-muted);\n }\n\n .e-search .e-input {\n flex: 1;\n text-overflow: ellipsis;\n height: 100%;\n border: 0;\n outline: 0;\n background: transparent;\n box-shadow: none;\n font-size: var(--e-text-md);\n padding-inline: var(--e-space-2);\n }\n\n .e-search .e-input:hover,\n .e-search .e-input:focus {\n border: 0;\n background: transparent;\n }\n\n .e-search .e-input:focus-visible {\n outline: none;\n }\n\n .e-search:focus-within {\n --e-ring: var(--e-focus-field);\n\n background: var(--e-surface);\n outline: max(var(--e-stroke-focus), calc(2 * var(--e-stroke-edge))) solid var(--e-focus-field);\n outline-offset: var(--e-focus-gap-field);\n }\n\n @media (prefers-reduced-motion: reduce) {\n .e-search {\n transition: none;\n }\n }\n\n @media print {\n .e-search {\n display: none;\n }\n }\n}\n</style>\n"],"mappings":""}
@@ -7,7 +7,7 @@ type __VLS_Props = {
7
7
  action?: string;
8
8
  /** Leaves out the button, for a box that filters or searches as you type. Enter still submits. */
9
9
  hideAction?: boolean;
10
- /** The clear button, shown when there is text. On by default. */
10
+ /** The clear button, shown when there is text. */
11
11
  clearable?: boolean;
12
12
  /** The name submitted with a form. @default "q" */
13
13
  name?: string;
@@ -1 +1 @@
1
- {"version":3,"file":"ESearchBar.vue_vue_type_script_setup_true_lang.js","names":["_useModel","_openBlock","_createElementBlock","_mergeProps","_unref","_withModifiers","_createElementVNode","_createVNode","EIcon","_createCommentVNode","_createBlock","EButton","_withCtx","_createTextVNode","_toDisplayString","EIcon_default","EButton_default","_hoisted_1","_hoisted_2","_hoisted_3","_hoisted_4","ESearchBar_vue_vue_type_script_setup_true_lang_default","\"modelValue\"","\"modelModifiers\"","__expose","__emit","emit","model","useModel","__props","t","useMessages","attrs","useFieldAttrs","box","ref","clear","openBlock","createElementBlock","mergeProps","unref","_cache","withModifiers","createElementVNode","createVNode","$event","createCommentVNode","createBlock","withCtx","createTextVNode","toDisplayString"],"sources":["../../../src/components/SearchBar/ESearchBar.vue"],"sourcesContent":["<script setup lang=\"ts\">\nimport EIcon from \"../Icon/EIcon.vue\";\nimport EButton from \"../Button/EButton.vue\";\nimport { ref } from \"vue\";\nimport { useMessages } from \"../../config.js\";\nimport { useFieldAttrs } from \"../../composables/useFieldAttrs.js\";\nimport \"../../styles/base.css\";\nimport \"../TextField/input.css\";\n\ndefineOptions({ inheritAttrs: false });\n\nwithDefaults(\n defineProps<{\n /** Names the box and the search landmark; there is no visible label. @default \"Search\" */\n label?: string;\n /** Say what can be searched, briefly. @default \"Search\" */\n placeholder?: string;\n /** The text on the button. @default \"Search\" */\n action?: string;\n /** Leaves out the button, for a box that filters or searches as you type. Enter still submits. */\n hideAction?: boolean;\n /** The clear button, shown when there is text. On by default. */\n clearable?: boolean;\n /** The name submitted with a form. @default \"q\" */\n name?: string;\n /** Disables the box and button. Say why in an `ENotice`. */\n disabled?: boolean;\n }>(),\n { clearable: true },\n);\n\nconst emit = defineEmits<{\n /** The person pressed Enter or the button. */\n submit: [value: string];\n}>();\n\n/** The text. */\nconst model = defineModel<string>({ default: \"\" });\n\nconst t = useMessages();\nconst attrs = useFieldAttrs();\nconst box = ref<HTMLInputElement | null>(null);\n\nfunction clear() {\n model.value = \"\";\n box.value?.focus();\n}\n\ndefineExpose({\n input: box,\n focus: () => box.value?.focus(),\n});\n</script>\n\n<template>\n <form\n class=\"e-search\"\n v-bind=\"attrs.wrapper()\"\n role=\"search\"\n :aria-label=\"label || t('search')\"\n @submit.prevent=\"emit('submit', model)\"\n >\n <span class=\"e-search-lead\"><EIcon name=\"search\" /></span>\n <input\n ref=\"box\"\n v-bind=\"attrs.input()\"\n class=\"e-input\"\n :name=\"name || 'q'\"\n :aria-label=\"label || t('search')\"\n :placeholder=\"placeholder || t('search')\"\n :value=\"model\"\n :disabled=\"disabled\"\n @input=\"model = ($event.target as HTMLInputElement).value\"\n />\n <button\n v-if=\"clearable && model && !disabled\"\n type=\"button\"\n class=\"e-search-clear\"\n :aria-label=\"t('clear')\"\n @mousedown.prevent\n @click=\"clear\"\n >\n <EIcon name=\"x\" />\n </button>\n <EButton v-if=\"!hideAction\" type=\"submit\" :disabled=\"disabled\">{{ action || t(\"search\") }}</EButton>\n </form>\n</template>\n\n<style>\n@layer e.controls {\n .e-search {\n display: flex;\n align-items: center;\n gap: var(--e-space-1);\n height: var(--e-control-height);\n padding: 0 var(--e-space-1) 0 var(--e-space-2);\n border: var(--e-stroke-edge) solid var(--e-border-strong);\n border-radius: var(--e-radius-md);\n background: var(--e-surface);\n box-shadow: var(--e-well);\n transition: border-color var(--e-duration-tap) var(--e-easing-out);\n }\n\n .e-search:hover {\n border-color: var(--e-ink);\n\n }\n\n .e-search .e-btn {\n position: relative;\n height: calc(var(--e-control-height) - 6px - var(--e-lift));\n padding: 0 var(--e-space-3);\n font-size: var(--e-text-md);\n }\n\n .e-search .e-btn::after {\n content: \"\";\n position: absolute;\n inset: -3px;\n }\n\n .e-search-clear {\n display: inline-grid;\n place-items: center;\n position: relative;\n flex: none;\n width: calc(var(--e-control-height) - 9px);\n height: calc(var(--e-control-height) - 9px);\n padding: 0;\n border: 0;\n border-radius: var(--e-radius-sm);\n background: transparent;\n color: var(--e-ink);\n cursor: pointer;\n transition: background-color var(--e-duration-tap) var(--e-easing-out);\n }\n\n .e-search-clear::after {\n content: \"\";\n position: absolute;\n inset: -5px;\n }\n\n .e-search-clear:hover {\n background: var(--e-wash-hover);\n box-shadow: inset 0 0 0 var(--e-stroke-hair) var(--e-wash-ring);\n }\n\n .e-search-clear:active {\n background: var(--e-wash-press);\n box-shadow: inset 0 0 0 var(--e-stroke-edge) var(--e-ink);\n }\n\n .e-search-clear:focus-visible {\n outline: var(--e-stroke-focus) solid var(--e-focus-ring);\n outline-offset: calc(-1 * var(--e-stroke-focus));\n }\n\n .e-search-lead {\n display: grid;\n place-items: center;\n flex: none;\n width: var(--e-space-8);\n color: var(--e-muted);\n }\n\n .e-search .e-input {\n flex: 1;\n text-overflow: ellipsis;\n height: 100%;\n border: 0;\n outline: 0;\n background: transparent;\n box-shadow: none;\n font-size: var(--e-text-md);\n padding-inline: var(--e-space-2);\n }\n\n .e-search .e-input:hover,\n .e-search .e-input:focus {\n border: 0;\n background: transparent;\n }\n\n .e-search .e-input:focus-visible {\n outline: none;\n }\n\n .e-search:focus-within {\n border-color: var(--e-focus-field);\n outline: var(--e-stroke-focus) solid var(--e-focus-field);\n outline-offset: var(--e-focus-gap-field);\n }\n\n @media (prefers-reduced-motion: reduce) {\n .e-search {\n transition: none;\n }\n }\n\n @media print {\n .e-search {\n display: none;\n }\n }\n}\n</style>\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;EA+BA,IAAM0B,IAAOD,GAMPE,IAAQ3B,EAAmB6B,GAAA,YAAgB,GAE3CC,IAAIC,EAAY,GAChBC,IAAQC,EAAc,GACtBC,IAAMC,EAA6B,IAAI;EAE7C,SAASC,IAAQ;GAEf,AADA,EAAM,QAAQ,IACdF,EAAI,OAAO,MAAM;EACnB;E,OAEAV,EAAa;GACX,OAAOU;GACP,aAAaA,EAAI,OAAO,MAAM;EAChC,CAAC,I,UAICjC,EAAA,GAAAC,EA8BO,QA9BPC,EA8BO,EA7BL,OAAM,WAAU,GACRC,EAAA4B,CAAA,CAAK,CAAC,QAAO,GAAA;GACrB,MAAK;GACJ,cAAYH,EAAA,SAASzB,EAAA0B,CAAA,CAAC,CAAA,QAAA;GACtB,UAAM,AAAAW,EAAA,OAAApC,GAAA,MAAUqB,EAAI,UAAWC,EAAA,KAAK,GAAA,CAAA,SAAA,CAAA;;GAErCrB,EAA0D,QAA1DY,GAA0D,CAA9BX,EAAuBC,GAAA,EAAhB,MAAK,SAAQ,CAAA,C;GAChDF,EAUE,SAVFH,EAUE;IATI,SAAA;IAAJ,KAAI+B;GACI,GAAA9B,EAAA4B,CAAA,CAAK,CAAC,MAAK,GAAA;IACnB,OAAM;IACL,MAAMH,EAAA,QAAI;IACV,cAAYA,EAAA,SAASzB,EAAA0B,CAAA,CAAC,CAAA,QAAA;IACtB,aAAaD,EAAA,eAAezB,EAAA0B,CAAA,CAAC,CAAA,QAAA;IAC7B,OAAOH,EAAA;IACP,UAAUE,EAAA;IACV,SAAK,AAAAY,EAAA,QAAA,MAAE,EAAA,QAASI,EAAO,OAA4B;;GAG9ChB,EAAA,aAAaF,EAAA,SAAK,CAAKE,EAAA,YAD/B5B,EAAA,GAAAC,EASS,UAAA;;IAPP,MAAK;IACL,OAAM;IACL,cAAYE,EAAA0B,CAAA,CAAC,CAAA,OAAA;IACb,aAAS,AAAAW,EAAA,OAAApC,QAAV,CAAA,GAAkB,CAAA,SAAA,CAAA;IACjB,SAAO+B;G,IAER7B,EAAkBC,GAAA,EAAX,MAAK,IAAG,CAAA,C;GAEDqB,EAAA,a,aAAhB5B,EAAA,GAAAS,EAAoGC,GAAA;;IAAxE,MAAK;IAAU,UAAUkB,EAAA;;IAAU,SAAAjB,QAA2B,CAAxBC,EAAAC,EAAAe,EAAA,UAAUzB,EAAA0B,CAAA,CAAC,CAAA,QAAA,CAAA,GAAA,CAAA,C"}
1
+ {"version":3,"file":"ESearchBar.vue_vue_type_script_setup_true_lang.js","names":["_useModel","_openBlock","_createElementBlock","_mergeProps","_unref","_withModifiers","_createElementVNode","_createVNode","EIcon","_createCommentVNode","_createBlock","EButton","_withCtx","_createTextVNode","_toDisplayString","EIcon_default","EButton_default","_hoisted_1","_hoisted_2","_hoisted_3","_hoisted_4","ESearchBar_vue_vue_type_script_setup_true_lang_default","\"modelValue\"","\"modelModifiers\"","__expose","__emit","emit","model","useModel","__props","t","useMessages","attrs","useFieldAttrs","box","ref","clear","openBlock","createElementBlock","mergeProps","unref","_cache","withModifiers","createElementVNode","createVNode","$event","createCommentVNode","createBlock","withCtx","createTextVNode","toDisplayString"],"sources":["../../../src/components/SearchBar/ESearchBar.vue"],"sourcesContent":["<script setup lang=\"ts\">\nimport EIcon from \"../Icon/EIcon.vue\";\nimport EButton from \"../Button/EButton.vue\";\nimport { ref } from \"vue\";\nimport { useMessages } from \"../../config.js\";\nimport { useFieldAttrs } from \"../../composables/useFieldAttrs.js\";\nimport \"../../styles/base.css\";\nimport \"../TextField/input.css\";\n\ndefineOptions({ inheritAttrs: false });\n\nwithDefaults(\n defineProps<{\n /** Names the box and the search landmark; there is no visible label. @default \"Search\" */\n label?: string;\n /** Say what can be searched, briefly. @default \"Search\" */\n placeholder?: string;\n /** The text on the button. @default \"Search\" */\n action?: string;\n /** Leaves out the button, for a box that filters or searches as you type. Enter still submits. */\n hideAction?: boolean;\n /** The clear button, shown when there is text. */\n clearable?: boolean;\n /** The name submitted with a form. @default \"q\" */\n name?: string;\n /** Disables the box and button. Say why in an `ENotice`. */\n disabled?: boolean;\n }>(),\n { clearable: true },\n);\n\nconst emit = defineEmits<{\n /** The person pressed Enter or the button. */\n submit: [value: string];\n}>();\n\n/** The text. */\nconst model = defineModel<string>({ default: \"\" });\n\nconst t = useMessages();\nconst attrs = useFieldAttrs();\nconst box = ref<HTMLInputElement | null>(null);\n\nfunction clear() {\n model.value = \"\";\n box.value?.focus();\n}\n\ndefineExpose({\n input: box,\n focus: () => box.value?.focus(),\n});\n</script>\n\n<template>\n <form\n class=\"e-search\"\n v-bind=\"attrs.wrapper()\"\n role=\"search\"\n :aria-label=\"label || t('search')\"\n @submit.prevent=\"emit('submit', model)\"\n >\n <span class=\"e-search-lead\"><EIcon name=\"search\" /></span>\n <input\n ref=\"box\"\n v-bind=\"attrs.input()\"\n class=\"e-input\"\n :name=\"name || 'q'\"\n :aria-label=\"label || t('search')\"\n :placeholder=\"placeholder || t('search')\"\n :value=\"model\"\n :disabled=\"disabled\"\n @input=\"model = ($event.target as HTMLInputElement).value\"\n />\n <button\n v-if=\"clearable && model && !disabled\"\n type=\"button\"\n class=\"e-search-clear\"\n :aria-label=\"t('clear')\"\n @mousedown.prevent\n @click=\"clear\"\n >\n <EIcon name=\"x\" />\n </button>\n <EButton v-if=\"!hideAction\" type=\"submit\" :disabled=\"disabled\">{{ action || t(\"search\") }}</EButton>\n </form>\n</template>\n\n<style>\n@layer e.controls {\n .e-search {\n --e-ring: var(--e-border-strong);\n\n display: flex;\n align-items: center;\n gap: var(--e-space-1);\n height: var(--e-control-height);\n padding: 0 var(--e-space-1) 0 var(--e-space-2);\n border-radius: var(--e-radius-md);\n background: var(--e-surface);\n box-shadow:\n inset 0 0 0 var(--e-stroke-edge) var(--e-ring),\n var(--e-well);\n transition: box-shadow var(--e-duration-tap) var(--e-easing-out);\n }\n\n .e-search:hover {\n background: var(--e-surface-hover);\n }\n\n .e-search .e-btn {\n position: relative;\n height: calc(var(--e-control-height) - 6px);\n padding: 0 var(--e-space-3) var(--e-lift);\n font-size: var(--e-text-md);\n }\n\n .e-search .e-btn::after {\n content: \"\";\n position: absolute;\n inset: -3px;\n }\n\n .e-search-clear {\n display: inline-grid;\n place-items: center;\n position: relative;\n flex: none;\n width: calc(var(--e-control-height) - 9px);\n height: calc(var(--e-control-height) - 9px);\n padding: 0;\n border: 0;\n border-radius: var(--e-radius-sm);\n background: transparent;\n color: var(--e-ink);\n cursor: pointer;\n transition: background-color var(--e-duration-tap) var(--e-easing-out);\n }\n\n .e-search-clear::after {\n content: \"\";\n position: absolute;\n inset: -5px;\n }\n\n .e-search-clear:hover {\n background: var(--e-wash-hover);\n box-shadow: inset 0 0 0 var(--e-stroke-hair) var(--e-wash-ring);\n }\n\n .e-search-clear:active {\n background: var(--e-wash-press);\n box-shadow: inset 0 0 0 var(--e-stroke-edge) var(--e-ink);\n }\n\n .e-search-clear:focus-visible {\n outline: var(--e-stroke-focus) solid var(--e-focus-ring);\n outline-offset: calc(-1 * var(--e-stroke-focus));\n }\n\n .e-search-lead {\n display: grid;\n place-items: center;\n flex: none;\n width: var(--e-space-8);\n color: var(--e-muted);\n }\n\n .e-search .e-input {\n flex: 1;\n text-overflow: ellipsis;\n height: 100%;\n border: 0;\n outline: 0;\n background: transparent;\n box-shadow: none;\n font-size: var(--e-text-md);\n padding-inline: var(--e-space-2);\n }\n\n .e-search .e-input:hover,\n .e-search .e-input:focus {\n border: 0;\n background: transparent;\n }\n\n .e-search .e-input:focus-visible {\n outline: none;\n }\n\n .e-search:focus-within {\n --e-ring: var(--e-focus-field);\n\n background: var(--e-surface);\n outline: max(var(--e-stroke-focus), calc(2 * var(--e-stroke-edge))) solid var(--e-focus-field);\n outline-offset: var(--e-focus-gap-field);\n }\n\n @media (prefers-reduced-motion: reduce) {\n .e-search {\n transition: none;\n }\n }\n\n @media print {\n .e-search {\n display: none;\n }\n }\n}\n</style>\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;EA+BA,IAAM0B,IAAOD,GAMPE,IAAQ3B,EAAmB6B,GAAA,YAAgB,GAE3CC,IAAIC,EAAY,GAChBC,IAAQC,EAAc,GACtBC,IAAMC,EAA6B,IAAI;EAE7C,SAASC,IAAQ;GAEf,AADA,EAAM,QAAQ,IACdF,EAAI,OAAO,MAAM;EACnB;E,OAEAV,EAAa;GACX,OAAOU;GACP,aAAaA,EAAI,OAAO,MAAM;EAChC,CAAC,I,UAICjC,EAAA,GAAAC,EA8BO,QA9BPC,EA8BO,EA7BL,OAAM,WAAU,GACRC,EAAA4B,CAAA,CAAK,CAAC,QAAO,GAAA;GACrB,MAAK;GACJ,cAAYH,EAAA,SAASzB,EAAA0B,CAAA,CAAC,CAAA,QAAA;GACtB,UAAM,AAAAW,EAAA,OAAApC,GAAA,MAAUqB,EAAI,UAAWC,EAAA,KAAK,GAAA,CAAA,SAAA,CAAA;;GAErCrB,EAA0D,QAA1DY,GAA0D,CAA9BX,EAAuBC,GAAA,EAAhB,MAAK,SAAQ,CAAA,C;GAChDF,EAUE,SAVFH,EAUE;IATI,SAAA;IAAJ,KAAI+B;GACI,GAAA9B,EAAA4B,CAAA,CAAK,CAAC,MAAK,GAAA;IACnB,OAAM;IACL,MAAMH,EAAA,QAAI;IACV,cAAYA,EAAA,SAASzB,EAAA0B,CAAA,CAAC,CAAA,QAAA;IACtB,aAAaD,EAAA,eAAezB,EAAA0B,CAAA,CAAC,CAAA,QAAA;IAC7B,OAAOH,EAAA;IACP,UAAUE,EAAA;IACV,SAAK,AAAAY,EAAA,QAAA,MAAE,EAAA,QAASI,EAAO,OAA4B;;GAG9ChB,EAAA,aAAaF,EAAA,SAAK,CAAKE,EAAA,YAD/B5B,EAAA,GAAAC,EASS,UAAA;;IAPP,MAAK;IACL,OAAM;IACL,cAAYE,EAAA0B,CAAA,CAAC,CAAA,OAAA;IACb,aAAS,AAAAW,EAAA,OAAApC,QAAV,CAAA,GAAkB,CAAA,SAAA,CAAA;IACjB,SAAO+B;G,IAER7B,EAAkBC,GAAA,EAAX,MAAK,IAAG,CAAA,C;GAEDqB,EAAA,a,aAAhB5B,EAAA,GAAAS,EAAoGC,GAAA;;IAAxE,MAAK;IAAU,UAAUkB,EAAA;;IAAU,SAAAjB,QAA2B,CAAxBC,EAAAC,EAAAe,EAAA,UAAUzB,EAAA0B,CAAA,CAAC,CAAA,QAAA,CAAA,GAAA,CAAA,C"}
@@ -1 +1 @@
1
- {"version":3,"file":"ESegmented.js","names":["_sfc_main","ESegmented_vue_vue_type_script_setup_true_lang_default","ESegmented_default"],"sources":["../../../src/components/Segmented/ESegmented.vue"],"sourcesContent":["<script lang=\"ts\">\nimport type { IconProp } from \"../../icons/types.js\";\n\nexport interface SegmentedOption {\n value: string;\n label: string;\n /** An icon before the label. */\n icon?: IconProp;\n disabled?: boolean;\n}\n</script>\n\n<script setup lang=\"ts\">\nimport { computed } from \"vue\";\nimport EIcon from \"../Icon/EIcon.vue\";\nimport EFieldMessage from \"../Field/EFieldMessage.vue\";\nimport { useMessages } from \"../../config.js\";\nimport { useFieldAttrs } from \"../../composables/useFieldAttrs.js\";\nimport { useUid } from \"../../composables/useUid.js\";\nimport \"../../styles/base.css\";\n\ndefineOptions({ inheritAttrs: false });\n\nconst props = defineProps<{\n /** Read by screen readers as the name of the group. */\n label: string;\n /** Two to five. A string is both value and label. `SegmentedOption` is `{ value, label, icon?, disabled? }`. */\n options: (string | SegmentedOption)[];\n /** Help under the control, linked with `aria-describedby`. */\n hint?: string;\n /** What to fix. Replaces the hint and is announced. */\n error?: string;\n /** Adds the word \"Optional\" to the group's accessible name; nothing is shown. Flag whichever is rarer. */\n optional?: boolean;\n /** Disables every option. */\n disabled?: boolean;\n /** The name the radios share, submitted with a form. @default generated */\n name?: string;\n}>();\n\n/** The active value. @default first option */\nconst model = defineModel<string>();\n\nconst t = useMessages();\nconst name = useUid(() => props.name);\nconst hintId = computed(() => `${name.value}-hint`);\nconst options = computed<SegmentedOption[]>(() =>\n props.options.map((o) => (typeof o === \"string\" ? { value: o, label: o } : o)),\n);\nconst current = computed(() => model.value ?? options.value[0]?.value);\nconst attrs = useFieldAttrs();\nconst groupAttrs = () => ({\n role: \"radiogroup\",\n \"aria-label\": props.optional ? `${props.label}, ${t(\"optional\")}` : props.label,\n \"aria-invalid\": props.error ? (\"true\" as const) : undefined,\n ...attrs.input(props.error || props.hint ? hintId.value : undefined),\n});\n</script>\n\n<template>\n <div v-if=\"hint || error\" class=\"e-seg-field\" :class=\"attrs.wrapper().class\" :style=\"attrs.wrapper().style\">\n <div class=\"e-seg\" v-bind=\"groupAttrs()\">\n <label v-for=\"o in options\" :key=\"o.value\" class=\"e-seg-opt\">\n <input\n type=\"radio\"\n class=\"e-seg-input\"\n :name=\"name\"\n :value=\"o.value\"\n :checked=\"current === o.value\"\n :disabled=\"o.disabled || disabled\"\n @change=\"model = o.value\"\n />\n <span class=\"e-seg-text\"><EIcon v-if=\"o.icon\" :name=\"o.icon\" />{{ o.label }}</span>\n </label>\n </div>\n <EFieldMessage :id=\"hintId\" :error=\"error\" :hint=\"hint\" />\n </div>\n <div v-else class=\"e-seg\" :class=\"attrs.wrapper().class\" :style=\"attrs.wrapper().style\" v-bind=\"groupAttrs()\">\n <label v-for=\"o in options\" :key=\"o.value\" class=\"e-seg-opt\">\n <input\n type=\"radio\"\n class=\"e-seg-input\"\n :name=\"name\"\n :value=\"o.value\"\n :checked=\"current === o.value\"\n :disabled=\"o.disabled || disabled\"\n @change=\"model = o.value\"\n />\n <span class=\"e-seg-text\"><EIcon v-if=\"o.icon\" :name=\"o.icon\" />{{ o.label }}</span>\n </label>\n </div>\n</template>\n\n<style>\n@layer e.controls {\n .e-seg {\n display: inline-flex;\n height: var(--e-control-height);\n border: var(--e-stroke-edge) solid var(--e-border-strong);\n border-radius: var(--e-radius-md);\n background: var(--e-border-strong);\n overflow: hidden;\n max-width: 100%;\n width: fit-content;\n }\n\n .e-seg-opt {\n position: relative;\n display: inline-flex;\n cursor: pointer;\n }\n\n .e-seg-opt + .e-seg-opt {\n border-inline-start: var(--e-stroke-hair) solid var(--e-border-strong);\n }\n\n .e-seg-input {\n position: absolute;\n inset: 0;\n opacity: 0;\n margin: 0;\n cursor: pointer;\n }\n\n .e-seg-text {\n display: inline-flex;\n align-items: center;\n justify-content: center;\n gap: var(--e-space-2);\n min-width: 4rem;\n padding: 0 var(--e-space-4);\n background: var(--e-surface);\n font: 500 var(--e-text-md)/1 var(--e-font-sans);\n white-space: nowrap;\n transition: background-color var(--e-duration-tap) var(--e-easing-out);\n }\n\n .e-seg-opt:hover .e-seg-text {\n background: var(--e-surface-hover);\n }\n\n .e-seg-input:checked + .e-seg-text {\n background: var(--e-primary);\n color: var(--e-on-primary);\n font-weight: 600;\n }\n\n .e-seg-input:focus-visible + .e-seg-text {\n outline: var(--e-stroke-focus) solid var(--e-focus-ring);\n outline-offset: calc(-1 * var(--e-space-1));\n }\n\n .e-seg-input:disabled + .e-seg-text {\n color: var(--e-muted);\n cursor: not-allowed;\n }\n\n .e-seg-opt:has(:disabled):hover .e-seg-text {\n background: transparent;\n }\n\n .e-seg-input:disabled:checked + .e-seg-text,\n .e-seg-opt:has(:disabled:checked):hover .e-seg-text {\n background: var(--e-surface-hover);\n color: var(--e-ink);\n }\n\n .e-seg-field {\n display: grid;\n gap: var(--e-space-2);\n }\n\n @media (prefers-reduced-motion: reduce) {\n .e-seg-text {\n transition: none;\n }\n }\n\n @media (forced-colors: active) {\n .e-seg-input:checked + .e-seg-text {\n forced-color-adjust: none;\n background: Highlight;\n color: HighlightText;\n }\n }\n}\n</style>\n"],"mappings":""}
1
+ {"version":3,"file":"ESegmented.js","names":["_sfc_main","ESegmented_vue_vue_type_script_setup_true_lang_default","ESegmented_default"],"sources":["../../../src/components/Segmented/ESegmented.vue"],"sourcesContent":["<script lang=\"ts\">\nimport type { IconProp } from \"../../icons/types.js\";\n\nexport interface SegmentedOption {\n value: string;\n label: string;\n /** An icon before the label. */\n icon?: IconProp;\n disabled?: boolean;\n}\n</script>\n\n<script setup lang=\"ts\">\nimport { computed } from \"vue\";\nimport EIcon from \"../Icon/EIcon.vue\";\nimport EFieldMessage from \"../Field/EFieldMessage.vue\";\nimport { useMessages } from \"../../config.js\";\nimport { useFieldAttrs } from \"../../composables/useFieldAttrs.js\";\nimport { useUid } from \"../../composables/useUid.js\";\nimport \"../../styles/base.css\";\n\ndefineOptions({ inheritAttrs: false });\n\nconst props = defineProps<{\n /** Read by screen readers as the name of the group. */\n label: string;\n /** Two to five. A string is both value and label. `SegmentedOption` is `{ value, label, icon?, disabled? }`. */\n options: (string | SegmentedOption)[];\n /** Help under the control, linked with `aria-describedby`. */\n hint?: string;\n /** What to fix. Replaces the hint and is announced. */\n error?: string;\n /** Adds the word \"Optional\" to the group's accessible name; nothing is shown. Flag whichever is rarer. */\n optional?: boolean;\n /** Disables every option. */\n disabled?: boolean;\n /** The name the radios share, submitted with a form. @default generated */\n name?: string;\n}>();\n\n/** The active value. @default first option */\nconst model = defineModel<string>();\n\nconst t = useMessages();\nconst name = useUid(() => props.name);\nconst hintId = computed(() => `${name.value}-hint`);\nconst options = computed<SegmentedOption[]>(() =>\n props.options.map((o) => (typeof o === \"string\" ? { value: o, label: o } : o)),\n);\nconst current = computed(() => model.value ?? options.value[0]?.value);\nconst attrs = useFieldAttrs();\nconst groupAttrs = () => ({\n role: \"radiogroup\",\n \"aria-label\": props.optional ? `${props.label}, ${t(\"optional\")}` : props.label,\n \"aria-invalid\": props.error ? (\"true\" as const) : undefined,\n ...attrs.input(props.error || props.hint ? hintId.value : undefined),\n});\n</script>\n\n<template>\n <div v-if=\"hint || error\" class=\"e-seg-field\" :class=\"attrs.wrapper().class\" :style=\"attrs.wrapper().style\">\n <div class=\"e-seg\" v-bind=\"groupAttrs()\">\n <label v-for=\"o in options\" :key=\"o.value\" class=\"e-seg-opt\">\n <input\n type=\"radio\"\n class=\"e-seg-input\"\n :name=\"name\"\n :value=\"o.value\"\n :checked=\"current === o.value\"\n :disabled=\"o.disabled || disabled\"\n @change=\"model = o.value\"\n />\n <span class=\"e-seg-text\"><EIcon v-if=\"o.icon\" :name=\"o.icon\" />{{ o.label }}</span>\n </label>\n </div>\n <EFieldMessage :id=\"hintId\" :error=\"error\" :hint=\"hint\" />\n </div>\n <div v-else class=\"e-seg\" :class=\"attrs.wrapper().class\" :style=\"attrs.wrapper().style\" v-bind=\"groupAttrs()\">\n <label v-for=\"o in options\" :key=\"o.value\" class=\"e-seg-opt\">\n <input\n type=\"radio\"\n class=\"e-seg-input\"\n :name=\"name\"\n :value=\"o.value\"\n :checked=\"current === o.value\"\n :disabled=\"o.disabled || disabled\"\n @change=\"model = o.value\"\n />\n <span class=\"e-seg-text\"><EIcon v-if=\"o.icon\" :name=\"o.icon\" />{{ o.label }}</span>\n </label>\n </div>\n</template>\n\n<style>\n@layer e.controls {\n /* A pressed-in track. The chosen option fills its cell edge to edge in the primary colour, covering the track's outline there so the outline turns primary where it is chosen, and the track clips it, so only the pieces at either end take the track's rounded corners: a value you set, not a place you go (that is Tabs). */\n .e-seg {\n display: inline-flex;\n box-sizing: border-box;\n height: var(--e-control-height);\n position: relative;\n border-radius: var(--e-radius-md);\n background: var(--e-surface-tint);\n box-shadow:\n inset 0 0 0 var(--e-stroke-edge) var(--e-border-strong),\n var(--e-well);\n overflow: hidden;\n max-width: 100%;\n width: fit-content;\n }\n\n .e-seg-opt {\n position: relative;\n display: inline-flex;\n cursor: pointer;\n }\n\n .e-seg-input {\n position: absolute;\n inset: 0;\n opacity: 0;\n margin: 0;\n cursor: pointer;\n }\n\n .e-seg-text {\n display: inline-flex;\n align-items: center;\n justify-content: center;\n gap: var(--e-space-2);\n box-sizing: border-box;\n min-width: 4rem;\n padding: 0 var(--e-space-4);\n background: transparent;\n color: var(--e-ink);\n font: 500 var(--e-text-md)/1 var(--e-font-sans);\n white-space: nowrap;\n transition: background-color var(--e-duration-tap) var(--e-easing-out);\n }\n\n .e-seg-opt:hover .e-seg-text {\n background: var(--e-wash-hover);\n }\n\n .e-seg-input:checked + .e-seg-text,\n .e-seg-opt:hover .e-seg-input:checked + .e-seg-text {\n background-color: var(--e-primary);\n\n /* The darker band along the bottom is the slab, drawn inside the piece and the track clips it to the corners. */\n background-image: linear-gradient(to top, color-mix(in srgb, var(--e-primary), var(--e-shade-slab)) var(--e-depth), transparent var(--e-depth));\n color: var(--e-on-primary);\n font-weight: 600;\n }\n\n .e-seg-input:focus-visible + .e-seg-text {\n outline: var(--e-stroke-focus) solid var(--e-focus-ring);\n outline-offset: calc(-1 * var(--e-space-1));\n }\n\n .e-seg-input:disabled + .e-seg-text {\n color: var(--e-muted);\n cursor: not-allowed;\n }\n\n .e-seg-opt:has(:disabled):hover .e-seg-text {\n background: transparent;\n }\n\n /* Chosen but unavailable: a flat piece with ink text, so it stays readable. */\n .e-seg-input:disabled:checked + .e-seg-text,\n .e-seg-opt:has(:disabled:checked):hover .e-seg-text {\n background-color: var(--e-surface);\n background-image: none;\n box-shadow: inset 0 0 0 var(--e-stroke-edge) var(--e-border-strong);\n color: var(--e-ink);\n }\n\n .e-seg-field {\n display: grid;\n gap: var(--e-space-2);\n }\n\n @media (prefers-reduced-motion: reduce) {\n .e-seg-text {\n transition: none;\n }\n }\n\n @media (forced-colors: active) {\n .e-seg-input:checked + .e-seg-text {\n forced-color-adjust: none;\n background: Highlight;\n color: HighlightText;\n }\n }\n}\n</style>\n"],"mappings":""}
@@ -1 +1 @@
1
- {"version":3,"file":"ESegmented.vue_vue_type_script_setup_true_lang.js","names":["_useModel","_openBlock","_createElementBlock","_normalizeClass","_unref","_normalizeStyle","_createElementVNode","_mergeProps","_Fragment","_renderList","_createBlock","EIcon","_createCommentVNode","_createTextVNode","_toDisplayString","_createVNode","EFieldMessage","EIcon_default","EFieldMessage_default","_hoisted_1","_hoisted_2","_hoisted_3","_hoisted_4","ESegmented_vue_vue_type_script_setup_true_lang_default","\"modelValue\"","\"modelModifiers\"","props","__props","model","useModel","t","useMessages","name","useUid","hintId","computed","options","o","current","attrs","useFieldAttrs","groupAttrs","openBlock","createElementBlock","normalizeClass","unref","normalizeStyle","createElementVNode","mergeProps","Fragment","renderList","createBlock","createCommentVNode","createTextVNode","toDisplayString","createVNode"],"sources":["../../../src/components/Segmented/ESegmented.vue"],"sourcesContent":["<script lang=\"ts\">\nimport type { IconProp } from \"../../icons/types.js\";\n\nexport interface SegmentedOption {\n value: string;\n label: string;\n /** An icon before the label. */\n icon?: IconProp;\n disabled?: boolean;\n}\n</script>\n\n<script setup lang=\"ts\">\nimport { computed } from \"vue\";\nimport EIcon from \"../Icon/EIcon.vue\";\nimport EFieldMessage from \"../Field/EFieldMessage.vue\";\nimport { useMessages } from \"../../config.js\";\nimport { useFieldAttrs } from \"../../composables/useFieldAttrs.js\";\nimport { useUid } from \"../../composables/useUid.js\";\nimport \"../../styles/base.css\";\n\ndefineOptions({ inheritAttrs: false });\n\nconst props = defineProps<{\n /** Read by screen readers as the name of the group. */\n label: string;\n /** Two to five. A string is both value and label. `SegmentedOption` is `{ value, label, icon?, disabled? }`. */\n options: (string | SegmentedOption)[];\n /** Help under the control, linked with `aria-describedby`. */\n hint?: string;\n /** What to fix. Replaces the hint and is announced. */\n error?: string;\n /** Adds the word \"Optional\" to the group's accessible name; nothing is shown. Flag whichever is rarer. */\n optional?: boolean;\n /** Disables every option. */\n disabled?: boolean;\n /** The name the radios share, submitted with a form. @default generated */\n name?: string;\n}>();\n\n/** The active value. @default first option */\nconst model = defineModel<string>();\n\nconst t = useMessages();\nconst name = useUid(() => props.name);\nconst hintId = computed(() => `${name.value}-hint`);\nconst options = computed<SegmentedOption[]>(() =>\n props.options.map((o) => (typeof o === \"string\" ? { value: o, label: o } : o)),\n);\nconst current = computed(() => model.value ?? options.value[0]?.value);\nconst attrs = useFieldAttrs();\nconst groupAttrs = () => ({\n role: \"radiogroup\",\n \"aria-label\": props.optional ? `${props.label}, ${t(\"optional\")}` : props.label,\n \"aria-invalid\": props.error ? (\"true\" as const) : undefined,\n ...attrs.input(props.error || props.hint ? hintId.value : undefined),\n});\n</script>\n\n<template>\n <div v-if=\"hint || error\" class=\"e-seg-field\" :class=\"attrs.wrapper().class\" :style=\"attrs.wrapper().style\">\n <div class=\"e-seg\" v-bind=\"groupAttrs()\">\n <label v-for=\"o in options\" :key=\"o.value\" class=\"e-seg-opt\">\n <input\n type=\"radio\"\n class=\"e-seg-input\"\n :name=\"name\"\n :value=\"o.value\"\n :checked=\"current === o.value\"\n :disabled=\"o.disabled || disabled\"\n @change=\"model = o.value\"\n />\n <span class=\"e-seg-text\"><EIcon v-if=\"o.icon\" :name=\"o.icon\" />{{ o.label }}</span>\n </label>\n </div>\n <EFieldMessage :id=\"hintId\" :error=\"error\" :hint=\"hint\" />\n </div>\n <div v-else class=\"e-seg\" :class=\"attrs.wrapper().class\" :style=\"attrs.wrapper().style\" v-bind=\"groupAttrs()\">\n <label v-for=\"o in options\" :key=\"o.value\" class=\"e-seg-opt\">\n <input\n type=\"radio\"\n class=\"e-seg-input\"\n :name=\"name\"\n :value=\"o.value\"\n :checked=\"current === o.value\"\n :disabled=\"o.disabled || disabled\"\n @change=\"model = o.value\"\n />\n <span class=\"e-seg-text\"><EIcon v-if=\"o.icon\" :name=\"o.icon\" />{{ o.label }}</span>\n </label>\n </div>\n</template>\n\n<style>\n@layer e.controls {\n .e-seg {\n display: inline-flex;\n height: var(--e-control-height);\n border: var(--e-stroke-edge) solid var(--e-border-strong);\n border-radius: var(--e-radius-md);\n background: var(--e-border-strong);\n overflow: hidden;\n max-width: 100%;\n width: fit-content;\n }\n\n .e-seg-opt {\n position: relative;\n display: inline-flex;\n cursor: pointer;\n }\n\n .e-seg-opt + .e-seg-opt {\n border-inline-start: var(--e-stroke-hair) solid var(--e-border-strong);\n }\n\n .e-seg-input {\n position: absolute;\n inset: 0;\n opacity: 0;\n margin: 0;\n cursor: pointer;\n }\n\n .e-seg-text {\n display: inline-flex;\n align-items: center;\n justify-content: center;\n gap: var(--e-space-2);\n min-width: 4rem;\n padding: 0 var(--e-space-4);\n background: var(--e-surface);\n font: 500 var(--e-text-md)/1 var(--e-font-sans);\n white-space: nowrap;\n transition: background-color var(--e-duration-tap) var(--e-easing-out);\n }\n\n .e-seg-opt:hover .e-seg-text {\n background: var(--e-surface-hover);\n }\n\n .e-seg-input:checked + .e-seg-text {\n background: var(--e-primary);\n color: var(--e-on-primary);\n font-weight: 600;\n }\n\n .e-seg-input:focus-visible + .e-seg-text {\n outline: var(--e-stroke-focus) solid var(--e-focus-ring);\n outline-offset: calc(-1 * var(--e-space-1));\n }\n\n .e-seg-input:disabled + .e-seg-text {\n color: var(--e-muted);\n cursor: not-allowed;\n }\n\n .e-seg-opt:has(:disabled):hover .e-seg-text {\n background: transparent;\n }\n\n .e-seg-input:disabled:checked + .e-seg-text,\n .e-seg-opt:has(:disabled:checked):hover .e-seg-text {\n background: var(--e-surface-hover);\n color: var(--e-ink);\n }\n\n .e-seg-field {\n display: grid;\n gap: var(--e-space-2);\n }\n\n @media (prefers-reduced-motion: reduce) {\n .e-seg-text {\n transition: none;\n }\n }\n\n @media (forced-colors: active) {\n .e-seg-input:checked + .e-seg-text {\n forced-color-adjust: none;\n background: Highlight;\n color: HighlightText;\n }\n }\n}\n</style>\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;EAuBA,IAAM0B,IAAQC,GAkBRC,IAAQ5B,EAAmB2B,GAAA,YAAC,GAE5BG,IAAIC,EAAY,GAChBC,IAAOC,QAAaP,EAAM,IAAI,GAC9BQ,IAASC,QAAe,GAAGH,EAAK,MAAM,MAAM,GAC5CI,IAAUD,QACdT,EAAM,QAAQ,KAAK,MAAO,OAAOW,KAAM,WAAW;GAAE,OAAOA;GAAG,OAAOA;EAAE,IAAIA,CAAE,CAC/E,GACMC,IAAUH,QAAeP,EAAM,SAASQ,EAAQ,MAAM,EAAE,EAAE,KAAK,GAC/DG,IAAQC,EAAc,GACtBC,WAAoB;GACxB,MAAM;GACN,cAAcf,EAAM,WAAW,GAAGA,EAAM,MAAM,IAAII,EAAE,UAAU,MAAMJ,EAAM;GAC1E,gBAAgBA,EAAM,QAAS,SAAmB,KAAA;GAClD,GAAGa,EAAM,MAAMb,EAAM,SAASA,EAAM,OAAOQ,EAAO,QAAQ,KAAA,CAAS;EACrE;E,iBAIaP,EAAA,QAAQA,EAAA,SAAnB1B,EAAA,GAAAC,EAgBM,OAAA;;GAhBoB,OAAKC,EAAA,CAAC,eAAsBC,EAAAmC,CAAA,CAAK,CAAC,QAAO,CAAA,CAAG,KAAK,CAAA;GAAG,OAAKlC,EAAED,EAAAmC,CAAA,CAAK,CAAC,QAAO,CAAA,CAAG,KAAK;E,IACxGjC,EAaM,OAbNC,EAaM,EAbD,OAAM,QAAO,GAASkC,EAAU,CAAA,GAAA,EACnCxC,EAAA,EAAA,GAAAC,EAWQM,GAAA,MAAAC,EAXW2B,EAAA,QAAL,OAAdnC,EAAA,GAAAC,EAWQ,SAAA;GAXqB,KAAKmC,EAAE;GAAO,OAAM;E,IAC/C/B,EAQE,SAAA;GAPA,MAAK;GACL,OAAM;GACL,MAAMF,EAAA4B,CAAA;GACN,OAAOK,EAAE;GACT,SAASC,EAAA,UAAYD,EAAE;GACvB,UAAUA,EAAE,YAAYV,EAAA;GACxB,WAAM,MAAE,EAAA,QAAQU,EAAE;E,iBAErB/B,EAAmF,QAAnFc,GAAmF,CAA7CiB,EAAE,QAAfpC,EAAA,GAAAS,EAAsCC,GAAA;;GAAhB,MAAM0B,EAAE;E,oCAAWxB,EAAAC,EAAAuB,EAAE,KAAK,GAAA,CAAA,C,qBAG7EtB,EAA0DC,GAAA;GAA1C,IAAIkB,EAAA;GAAS,OAAOP,EAAA;GAAQ,MAAMA,EAAA;;;;;E,YAEpD1B,EAAA,GAAAC,EAaM,OAbNK,EAaM;;GAbM,OAAK,CAAC,SAAgBH,EAAAmC,CAAA,CAAK,CAAC,QAAO,CAAA,CAAG,KAAK;GAAG,OAAOnC,EAAAmC,CAAA,CAAK,CAAC,QAAO,CAAA,CAAG;EAAe,GAAAE,EAAU,CAAA,GAAA,EACxGxC,EAAA,EAAA,GAAAC,EAWQM,GAAA,MAAAC,EAXW2B,EAAA,QAAL,OAAdnC,EAAA,GAAAC,EAWQ,SAAA;GAXqB,KAAKmC,EAAE;GAAO,OAAM;E,IAC/C/B,EAQE,SAAA;GAPA,MAAK;GACL,OAAM;GACL,MAAMF,EAAA4B,CAAA;GACN,OAAOK,EAAE;GACT,SAASC,EAAA,UAAYD,EAAE;GACvB,UAAUA,EAAE,YAAYV,EAAA;GACxB,WAAM,MAAE,EAAA,QAAQU,EAAE;E,iBAErB/B,EAAmF,QAAnFgB,GAAmF,CAA7Ce,EAAE,QAAfpC,EAAA,GAAAS,EAAsCC,GAAA;;GAAhB,MAAM0B,EAAE;E,oCAAWxB,EAAAC,EAAAuB,EAAE,KAAK,GAAA,CAAA,C"}
1
+ {"version":3,"file":"ESegmented.vue_vue_type_script_setup_true_lang.js","names":["_useModel","_openBlock","_createElementBlock","_normalizeClass","_unref","_normalizeStyle","_createElementVNode","_mergeProps","_Fragment","_renderList","_createBlock","EIcon","_createCommentVNode","_createTextVNode","_toDisplayString","_createVNode","EFieldMessage","EIcon_default","EFieldMessage_default","_hoisted_1","_hoisted_2","_hoisted_3","_hoisted_4","ESegmented_vue_vue_type_script_setup_true_lang_default","\"modelValue\"","\"modelModifiers\"","props","__props","model","useModel","t","useMessages","name","useUid","hintId","computed","options","o","current","attrs","useFieldAttrs","groupAttrs","openBlock","createElementBlock","normalizeClass","unref","normalizeStyle","createElementVNode","mergeProps","Fragment","renderList","createBlock","createCommentVNode","createTextVNode","toDisplayString","createVNode"],"sources":["../../../src/components/Segmented/ESegmented.vue"],"sourcesContent":["<script lang=\"ts\">\nimport type { IconProp } from \"../../icons/types.js\";\n\nexport interface SegmentedOption {\n value: string;\n label: string;\n /** An icon before the label. */\n icon?: IconProp;\n disabled?: boolean;\n}\n</script>\n\n<script setup lang=\"ts\">\nimport { computed } from \"vue\";\nimport EIcon from \"../Icon/EIcon.vue\";\nimport EFieldMessage from \"../Field/EFieldMessage.vue\";\nimport { useMessages } from \"../../config.js\";\nimport { useFieldAttrs } from \"../../composables/useFieldAttrs.js\";\nimport { useUid } from \"../../composables/useUid.js\";\nimport \"../../styles/base.css\";\n\ndefineOptions({ inheritAttrs: false });\n\nconst props = defineProps<{\n /** Read by screen readers as the name of the group. */\n label: string;\n /** Two to five. A string is both value and label. `SegmentedOption` is `{ value, label, icon?, disabled? }`. */\n options: (string | SegmentedOption)[];\n /** Help under the control, linked with `aria-describedby`. */\n hint?: string;\n /** What to fix. Replaces the hint and is announced. */\n error?: string;\n /** Adds the word \"Optional\" to the group's accessible name; nothing is shown. Flag whichever is rarer. */\n optional?: boolean;\n /** Disables every option. */\n disabled?: boolean;\n /** The name the radios share, submitted with a form. @default generated */\n name?: string;\n}>();\n\n/** The active value. @default first option */\nconst model = defineModel<string>();\n\nconst t = useMessages();\nconst name = useUid(() => props.name);\nconst hintId = computed(() => `${name.value}-hint`);\nconst options = computed<SegmentedOption[]>(() =>\n props.options.map((o) => (typeof o === \"string\" ? { value: o, label: o } : o)),\n);\nconst current = computed(() => model.value ?? options.value[0]?.value);\nconst attrs = useFieldAttrs();\nconst groupAttrs = () => ({\n role: \"radiogroup\",\n \"aria-label\": props.optional ? `${props.label}, ${t(\"optional\")}` : props.label,\n \"aria-invalid\": props.error ? (\"true\" as const) : undefined,\n ...attrs.input(props.error || props.hint ? hintId.value : undefined),\n});\n</script>\n\n<template>\n <div v-if=\"hint || error\" class=\"e-seg-field\" :class=\"attrs.wrapper().class\" :style=\"attrs.wrapper().style\">\n <div class=\"e-seg\" v-bind=\"groupAttrs()\">\n <label v-for=\"o in options\" :key=\"o.value\" class=\"e-seg-opt\">\n <input\n type=\"radio\"\n class=\"e-seg-input\"\n :name=\"name\"\n :value=\"o.value\"\n :checked=\"current === o.value\"\n :disabled=\"o.disabled || disabled\"\n @change=\"model = o.value\"\n />\n <span class=\"e-seg-text\"><EIcon v-if=\"o.icon\" :name=\"o.icon\" />{{ o.label }}</span>\n </label>\n </div>\n <EFieldMessage :id=\"hintId\" :error=\"error\" :hint=\"hint\" />\n </div>\n <div v-else class=\"e-seg\" :class=\"attrs.wrapper().class\" :style=\"attrs.wrapper().style\" v-bind=\"groupAttrs()\">\n <label v-for=\"o in options\" :key=\"o.value\" class=\"e-seg-opt\">\n <input\n type=\"radio\"\n class=\"e-seg-input\"\n :name=\"name\"\n :value=\"o.value\"\n :checked=\"current === o.value\"\n :disabled=\"o.disabled || disabled\"\n @change=\"model = o.value\"\n />\n <span class=\"e-seg-text\"><EIcon v-if=\"o.icon\" :name=\"o.icon\" />{{ o.label }}</span>\n </label>\n </div>\n</template>\n\n<style>\n@layer e.controls {\n /* A pressed-in track. The chosen option fills its cell edge to edge in the primary colour, covering the track's outline there so the outline turns primary where it is chosen, and the track clips it, so only the pieces at either end take the track's rounded corners: a value you set, not a place you go (that is Tabs). */\n .e-seg {\n display: inline-flex;\n box-sizing: border-box;\n height: var(--e-control-height);\n position: relative;\n border-radius: var(--e-radius-md);\n background: var(--e-surface-tint);\n box-shadow:\n inset 0 0 0 var(--e-stroke-edge) var(--e-border-strong),\n var(--e-well);\n overflow: hidden;\n max-width: 100%;\n width: fit-content;\n }\n\n .e-seg-opt {\n position: relative;\n display: inline-flex;\n cursor: pointer;\n }\n\n .e-seg-input {\n position: absolute;\n inset: 0;\n opacity: 0;\n margin: 0;\n cursor: pointer;\n }\n\n .e-seg-text {\n display: inline-flex;\n align-items: center;\n justify-content: center;\n gap: var(--e-space-2);\n box-sizing: border-box;\n min-width: 4rem;\n padding: 0 var(--e-space-4);\n background: transparent;\n color: var(--e-ink);\n font: 500 var(--e-text-md)/1 var(--e-font-sans);\n white-space: nowrap;\n transition: background-color var(--e-duration-tap) var(--e-easing-out);\n }\n\n .e-seg-opt:hover .e-seg-text {\n background: var(--e-wash-hover);\n }\n\n .e-seg-input:checked + .e-seg-text,\n .e-seg-opt:hover .e-seg-input:checked + .e-seg-text {\n background-color: var(--e-primary);\n\n /* The darker band along the bottom is the slab, drawn inside the piece and the track clips it to the corners. */\n background-image: linear-gradient(to top, color-mix(in srgb, var(--e-primary), var(--e-shade-slab)) var(--e-depth), transparent var(--e-depth));\n color: var(--e-on-primary);\n font-weight: 600;\n }\n\n .e-seg-input:focus-visible + .e-seg-text {\n outline: var(--e-stroke-focus) solid var(--e-focus-ring);\n outline-offset: calc(-1 * var(--e-space-1));\n }\n\n .e-seg-input:disabled + .e-seg-text {\n color: var(--e-muted);\n cursor: not-allowed;\n }\n\n .e-seg-opt:has(:disabled):hover .e-seg-text {\n background: transparent;\n }\n\n /* Chosen but unavailable: a flat piece with ink text, so it stays readable. */\n .e-seg-input:disabled:checked + .e-seg-text,\n .e-seg-opt:has(:disabled:checked):hover .e-seg-text {\n background-color: var(--e-surface);\n background-image: none;\n box-shadow: inset 0 0 0 var(--e-stroke-edge) var(--e-border-strong);\n color: var(--e-ink);\n }\n\n .e-seg-field {\n display: grid;\n gap: var(--e-space-2);\n }\n\n @media (prefers-reduced-motion: reduce) {\n .e-seg-text {\n transition: none;\n }\n }\n\n @media (forced-colors: active) {\n .e-seg-input:checked + .e-seg-text {\n forced-color-adjust: none;\n background: Highlight;\n color: HighlightText;\n }\n }\n}\n</style>\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;EAuBA,IAAM0B,IAAQC,GAkBRC,IAAQ5B,EAAmB2B,GAAA,YAAC,GAE5BG,IAAIC,EAAY,GAChBC,IAAOC,QAAaP,EAAM,IAAI,GAC9BQ,IAASC,QAAe,GAAGH,EAAK,MAAM,MAAM,GAC5CI,IAAUD,QACdT,EAAM,QAAQ,KAAK,MAAO,OAAOW,KAAM,WAAW;GAAE,OAAOA;GAAG,OAAOA;EAAE,IAAIA,CAAE,CAC/E,GACMC,IAAUH,QAAeP,EAAM,SAASQ,EAAQ,MAAM,EAAE,EAAE,KAAK,GAC/DG,IAAQC,EAAc,GACtBC,WAAoB;GACxB,MAAM;GACN,cAAcf,EAAM,WAAW,GAAGA,EAAM,MAAM,IAAII,EAAE,UAAU,MAAMJ,EAAM;GAC1E,gBAAgBA,EAAM,QAAS,SAAmB,KAAA;GAClD,GAAGa,EAAM,MAAMb,EAAM,SAASA,EAAM,OAAOQ,EAAO,QAAQ,KAAA,CAAS;EACrE;E,iBAIaP,EAAA,QAAQA,EAAA,SAAnB1B,EAAA,GAAAC,EAgBM,OAAA;;GAhBoB,OAAKC,EAAA,CAAC,eAAsBC,EAAAmC,CAAA,CAAK,CAAC,QAAO,CAAA,CAAG,KAAK,CAAA;GAAG,OAAKlC,EAAED,EAAAmC,CAAA,CAAK,CAAC,QAAO,CAAA,CAAG,KAAK;E,IACxGjC,EAaM,OAbNC,EAaM,EAbD,OAAM,QAAO,GAASkC,EAAU,CAAA,GAAA,EACnCxC,EAAA,EAAA,GAAAC,EAWQM,GAAA,MAAAC,EAXW2B,EAAA,QAAL,OAAdnC,EAAA,GAAAC,EAWQ,SAAA;GAXqB,KAAKmC,EAAE;GAAO,OAAM;E,IAC/C/B,EAQE,SAAA;GAPA,MAAK;GACL,OAAM;GACL,MAAMF,EAAA4B,CAAA;GACN,OAAOK,EAAE;GACT,SAASC,EAAA,UAAYD,EAAE;GACvB,UAAUA,EAAE,YAAYV,EAAA;GACxB,WAAM,MAAE,EAAA,QAAQU,EAAE;E,iBAErB/B,EAAmF,QAAnFc,GAAmF,CAA7CiB,EAAE,QAAfpC,EAAA,GAAAS,EAAsCC,GAAA;;GAAhB,MAAM0B,EAAE;E,oCAAWxB,EAAAC,EAAAuB,EAAE,KAAK,GAAA,CAAA,C,qBAG7EtB,EAA0DC,GAAA;GAA1C,IAAIkB,EAAA;GAAS,OAAOP,EAAA;GAAQ,MAAMA,EAAA;;;;;E,YAEpD1B,EAAA,GAAAC,EAaM,OAbNK,EAaM;;GAbM,OAAK,CAAC,SAAgBH,EAAAmC,CAAA,CAAK,CAAC,QAAO,CAAA,CAAG,KAAK;GAAG,OAAOnC,EAAAmC,CAAA,CAAK,CAAC,QAAO,CAAA,CAAG;EAAe,GAAAE,EAAU,CAAA,GAAA,EACxGxC,EAAA,EAAA,GAAAC,EAWQM,GAAA,MAAAC,EAXW2B,EAAA,QAAL,OAAdnC,EAAA,GAAAC,EAWQ,SAAA;GAXqB,KAAKmC,EAAE;GAAO,OAAM;E,IAC/C/B,EAQE,SAAA;GAPA,MAAK;GACL,OAAM;GACL,MAAMF,EAAA4B,CAAA;GACN,OAAOK,EAAE;GACT,SAASC,EAAA,UAAYD,EAAE;GACvB,UAAUA,EAAE,YAAYV,EAAA;GACxB,WAAM,MAAE,EAAA,QAAQU,EAAE;E,iBAErB/B,EAAmF,QAAnFgB,GAAmF,CAA7Ce,EAAE,QAAfpC,EAAA,GAAAS,EAAsCC,GAAA;;GAAhB,MAAM0B,EAAE;E,oCAAWxB,EAAAC,EAAAuB,EAAE,KAAK,GAAA,CAAA,C"}
@@ -1 +1 @@
1
- {"version":3,"file":"ESelectControl.js","names":["_sfc_main","ESelectControl_vue_vue_type_script_setup_true_lang_default","ESelectControl_default"],"sources":["../../../src/components/Select/ESelectControl.vue"],"sourcesContent":["<script setup lang=\"ts\">\nimport { computed, watch } from \"vue\";\nimport {\n SelectContent,\n SelectGroup,\n SelectLabel,\n SelectPortal,\n SelectRoot,\n SelectTrigger,\n SelectViewport,\n} from \"reka-ui\";\nimport EIcon from \"../Icon/EIcon.vue\";\nimport ESelectOption from \"./ESelectOption.vue\";\nimport { sectionOptions, type EOption } from \"./options.js\";\nimport { useMessages, usePortalTarget } from \"../../config.js\";\nimport { useQuietFocus } from \"./quietFocus.js\";\nimport \"../../styles/base.css\";\nimport \"../TextField/input.css\";\nimport \"./panel.css\";\n\nconst props = defineProps<{\n /** The normalised options. */\n options: EOption[];\n placeholder?: string | undefined;\n disabled?: boolean | undefined;\n required?: boolean | undefined;\n name?: string | undefined;\n /** Names the list. */\n label?: string | undefined;\n /** Attributes for the button: id, aria-*, data-*, listeners. */\n triggerAttrs: Record<string, unknown>;\n}>();\n\nconst model = defineModel<string>({ default: \"\" });\n\nconst t = useMessages();\nconst portal = usePortalTarget();\n\nconst sections = computed(() => sectionOptions(props.options));\nconst selected = computed(() => props.options.find((o) => o.value === model.value));\n\nlet typed = \"\";\nlet typedAt = 0;\nconst open = defineModel<boolean>(\"open\", { default: false });\nconst isOpen = computed(() => open.value && !props.disabled);\nconst quiet = useQuietFocus(isOpen, (el) => !!el.closest(\"[role=listbox]\"));\nwatch(\n isOpen,\n (now) => {\n if (now && !quiet.personOpened()) quiet.undoFocusSteal();\n },\n { immediate: true, flush: \"post\" },\n);\nfunction closeFocus(e: Event) {\n if (!quiet.returnsFocus()) e.preventDefault();\n}\nfunction keydown(e: KeyboardEvent) {\n quiet.intent();\n typeahead(e);\n}\nfunction typeahead(e: KeyboardEvent) {\n if (props.disabled || isOpen.value || e.ctrlKey || e.metaKey || e.altKey || e.key.length !== 1) return;\n if (e.key === \" \" && !typed) return;\n const now = Date.now();\n typed = (now - typedAt > 700 ? \"\" : typed) + e.key.toLowerCase();\n typedAt = now;\n const list = props.options;\n const from = list.findIndex((o) => o.value === model.value);\n for (let j = 0; j < list.length; j++) {\n const o = list[(from + j + (typed.length === 1 ? 1 : 0) + list.length) % list.length];\n if (o && !o.disabled && o.label.toLowerCase().startsWith(typed)) {\n model.value = o.value;\n break;\n }\n }\n}\n</script>\n\n<template>\n <div class=\"e-sel\">\n <SelectRoot v-model=\"model\" :open=\"isOpen\" :disabled=\"disabled\" :required=\"required\" @update:open=\"open = $event\">\n <SelectTrigger\n class=\"e-input e-sel-trigger\"\n :tabindex=\"isOpen ? -1 : undefined\"\n v-bind=\"triggerAttrs\"\n @pointerdown=\"quiet.intent\"\n @keydown=\"keydown\"\n >\n <span v-if=\"selected\" class=\"e-sel-value\">\n <EIcon v-if=\"selected.icon\" :name=\"selected.icon\" />{{ selected.label }}\n </span>\n <span v-else class=\"e-sel-placeholder\">{{ placeholder || t(\"select\") }}</span>\n <EIcon name=\"chevron-down\" bold />\n </SelectTrigger>\n <SelectPortal :to=\"portal\">\n <SelectContent\n position=\"popper\"\n align=\"start\"\n :side-offset=\"6\"\n :collision-padding=\"8\"\n :body-lock=\"false\"\n class=\"e-popover e-listpanel e-root\"\n :aria-label=\"label\"\n @close-auto-focus=\"closeFocus\"\n >\n <SelectViewport>\n <template v-for=\"(section, i) in sections\" :key=\"i\">\n <SelectGroup v-if=\"section.group\" class=\"e-opt-set\">\n <SelectLabel class=\"e-opt-group\">{{ section.group }}</SelectLabel>\n <ESelectOption v-for=\"o in section.options\" :key=\"o.value\" :option=\"o\" :selected=\"o.value === model\" />\n </SelectGroup>\n <template v-else>\n <ESelectOption v-for=\"o in section.options\" :key=\"o.value\" :option=\"o\" :selected=\"o.value === model\" />\n </template>\n </template>\n </SelectViewport>\n </SelectContent>\n </SelectPortal>\n </SelectRoot>\n <input v-if=\"name\" type=\"hidden\" :name=\"name\" :value=\"model\" />\n </div>\n</template>\n\n<style>\n@layer e.controls {\n .e-sel {\n position: relative;\n }\n\n .e-sel-trigger {\n display: flex;\n align-items: center;\n justify-content: space-between;\n gap: var(--e-space-2);\n padding-inline-end: var(--e-space-3);\n text-align: start;\n cursor: pointer;\n }\n\n .e-sel-trigger[aria-expanded=\"true\"] {\n border-color: var(--e-ink);\n background-color: var(--e-surface);\n }\n\n .e-sel-value {\n display: inline-flex;\n align-items: center;\n gap: var(--e-space-2);\n min-width: 0;\n overflow: hidden;\n line-height: 1.4;\n text-overflow: ellipsis;\n white-space: nowrap;\n }\n\n .e-sel-placeholder {\n color: var(--e-muted);\n }\n\n .e-sel-trigger > .e-icon {\n flex: none;\n }\n}\n</style>\n"],"mappings":""}
1
+ {"version":3,"file":"ESelectControl.js","names":["_sfc_main","ESelectControl_vue_vue_type_script_setup_true_lang_default","ESelectControl_default"],"sources":["../../../src/components/Select/ESelectControl.vue"],"sourcesContent":["<script setup lang=\"ts\">\nimport { computed, watch } from \"vue\";\nimport {\n SelectContent,\n SelectGroup,\n SelectLabel,\n SelectPortal,\n SelectRoot,\n SelectTrigger,\n SelectViewport,\n} from \"reka-ui\";\nimport EIcon from \"../Icon/EIcon.vue\";\nimport ESelectOption from \"./ESelectOption.vue\";\nimport { sectionOptions, type EOption } from \"./options.js\";\nimport { useMessages, usePortalTarget } from \"../../config.js\";\nimport { useQuietFocus } from \"./quietFocus.js\";\nimport \"../../styles/base.css\";\nimport \"../TextField/input.css\";\nimport \"./panel.css\";\n\nconst props = defineProps<{\n /** The normalised options. */\n options: EOption[];\n placeholder?: string | undefined;\n disabled?: boolean | undefined;\n required?: boolean | undefined;\n name?: string | undefined;\n /** Names the list. */\n label?: string | undefined;\n /** Attributes for the button: id, aria-*, data-*, listeners. */\n triggerAttrs: Record<string, unknown>;\n}>();\n\nconst model = defineModel<string>({ default: \"\" });\n\nconst t = useMessages();\nconst portal = usePortalTarget();\n\nconst sections = computed(() => sectionOptions(props.options));\nconst selected = computed(() => props.options.find((o) => o.value === model.value));\n\nlet typed = \"\";\nlet typedAt = 0;\nconst open = defineModel<boolean>(\"open\", { default: false });\nconst isOpen = computed(() => open.value && !props.disabled);\nconst quiet = useQuietFocus(isOpen, (el) => !!el.closest(\"[role=listbox]\"));\nwatch(\n isOpen,\n (now) => {\n if (now && !quiet.personOpened()) quiet.undoFocusSteal();\n },\n { immediate: true, flush: \"post\" },\n);\nfunction closeFocus(e: Event) {\n if (!quiet.returnsFocus()) e.preventDefault();\n}\nfunction keydown(e: KeyboardEvent) {\n quiet.intent();\n typeahead(e);\n}\nfunction typeahead(e: KeyboardEvent) {\n if (props.disabled || isOpen.value || e.ctrlKey || e.metaKey || e.altKey || e.key.length !== 1) return;\n if (e.key === \" \" && !typed) return;\n const now = Date.now();\n typed = (now - typedAt > 700 ? \"\" : typed) + e.key.toLowerCase();\n typedAt = now;\n const list = props.options;\n const from = list.findIndex((o) => o.value === model.value);\n for (let j = 0; j < list.length; j++) {\n const o = list[(from + j + (typed.length === 1 ? 1 : 0) + list.length) % list.length];\n if (o && !o.disabled && o.label.toLowerCase().startsWith(typed)) {\n model.value = o.value;\n break;\n }\n }\n}\n</script>\n\n<template>\n <div class=\"e-sel\">\n <SelectRoot v-model=\"model\" :open=\"isOpen\" :disabled=\"disabled\" :required=\"required\" @update:open=\"open = $event\">\n <SelectTrigger\n class=\"e-input e-sel-trigger\"\n :tabindex=\"isOpen ? -1 : undefined\"\n v-bind=\"triggerAttrs\"\n @pointerdown=\"quiet.intent\"\n @keydown=\"keydown\"\n >\n <span v-if=\"selected\" class=\"e-sel-value\">\n <EIcon v-if=\"selected.icon\" :name=\"selected.icon\" />{{ selected.label }}\n </span>\n <span v-else class=\"e-sel-placeholder\">{{ placeholder || t(\"select\") }}</span>\n <EIcon name=\"chevron-down\" bold />\n </SelectTrigger>\n <SelectPortal :to=\"portal\">\n <SelectContent\n position=\"popper\"\n align=\"start\"\n :side-offset=\"6\"\n :collision-padding=\"8\"\n :body-lock=\"false\"\n class=\"e-popover e-listpanel e-root\"\n :aria-label=\"label\"\n @close-auto-focus=\"closeFocus\"\n >\n <SelectViewport>\n <template v-for=\"(section, i) in sections\" :key=\"i\">\n <SelectGroup v-if=\"section.group\" class=\"e-opt-set\">\n <SelectLabel class=\"e-opt-group\">{{ section.group }}</SelectLabel>\n <ESelectOption v-for=\"o in section.options\" :key=\"o.value\" :option=\"o\" :selected=\"o.value === model\" />\n </SelectGroup>\n <template v-else>\n <ESelectOption v-for=\"o in section.options\" :key=\"o.value\" :option=\"o\" :selected=\"o.value === model\" />\n </template>\n </template>\n </SelectViewport>\n </SelectContent>\n </SelectPortal>\n </SelectRoot>\n <input v-if=\"name\" type=\"hidden\" :name=\"name\" :value=\"model\" />\n </div>\n</template>\n\n<style>\n@layer e.controls {\n .e-sel {\n position: relative;\n }\n\n .e-sel-trigger {\n display: flex;\n align-items: center;\n justify-content: space-between;\n gap: var(--e-space-2);\n padding-inline-end: var(--e-space-3);\n text-align: start;\n cursor: pointer;\n }\n\n .e-sel-trigger[aria-expanded=\"true\"] {\n --e-ring: var(--e-ink);\n\n background-color: var(--e-surface);\n }\n\n .e-sel-value {\n display: inline-flex;\n align-items: center;\n gap: var(--e-space-2);\n min-width: 0;\n overflow: hidden;\n line-height: 1.4;\n text-overflow: ellipsis;\n white-space: nowrap;\n }\n\n .e-sel-placeholder {\n color: var(--e-muted);\n }\n\n .e-sel-trigger > .e-icon {\n flex: none;\n }\n}\n</style>\n"],"mappings":""}
@@ -1 +1 @@
1
- {"version":3,"file":"ESelectControl.vue_vue_type_script_setup_true_lang.js","names":["_useModel","_openBlock","_createElementBlock","_createVNode","_unref","_withCtx","_mergeProps","_createBlock","EIcon","_createCommentVNode","_createTextVNode","_toDisplayString","_Fragment","_renderList","ESelectOption","EIcon_default","ESelectOption_default","_hoisted_1","_hoisted_2","_hoisted_3","_hoisted_4","ESelectControl_vue_vue_type_script_setup_true_lang_default","\"modelValue\"","\"modelModifiers\"","\"open\"","\"openModifiers\"","props","__props","model","useModel","t","useMessages","portal","usePortalTarget","sections","computed","sectionOptions","selected","o","typed","typedAt","open","isOpen","quiet","useQuietFocus","el","now","closeFocus","keydown","typeahead","list","from","j","openBlock","createElementBlock","createVNode","unref","SelectRoot","_cache","$event","withCtx","SelectTrigger","mergeProps","createBlock","createCommentVNode","createTextVNode","toDisplayString","SelectPortal","SelectContent","SelectViewport","Fragment","renderList","i","section","SelectGroup","SelectLabel"],"sources":["../../../src/components/Select/ESelectControl.vue"],"sourcesContent":["<script setup lang=\"ts\">\nimport { computed, watch } from \"vue\";\nimport {\n SelectContent,\n SelectGroup,\n SelectLabel,\n SelectPortal,\n SelectRoot,\n SelectTrigger,\n SelectViewport,\n} from \"reka-ui\";\nimport EIcon from \"../Icon/EIcon.vue\";\nimport ESelectOption from \"./ESelectOption.vue\";\nimport { sectionOptions, type EOption } from \"./options.js\";\nimport { useMessages, usePortalTarget } from \"../../config.js\";\nimport { useQuietFocus } from \"./quietFocus.js\";\nimport \"../../styles/base.css\";\nimport \"../TextField/input.css\";\nimport \"./panel.css\";\n\nconst props = defineProps<{\n /** The normalised options. */\n options: EOption[];\n placeholder?: string | undefined;\n disabled?: boolean | undefined;\n required?: boolean | undefined;\n name?: string | undefined;\n /** Names the list. */\n label?: string | undefined;\n /** Attributes for the button: id, aria-*, data-*, listeners. */\n triggerAttrs: Record<string, unknown>;\n}>();\n\nconst model = defineModel<string>({ default: \"\" });\n\nconst t = useMessages();\nconst portal = usePortalTarget();\n\nconst sections = computed(() => sectionOptions(props.options));\nconst selected = computed(() => props.options.find((o) => o.value === model.value));\n\nlet typed = \"\";\nlet typedAt = 0;\nconst open = defineModel<boolean>(\"open\", { default: false });\nconst isOpen = computed(() => open.value && !props.disabled);\nconst quiet = useQuietFocus(isOpen, (el) => !!el.closest(\"[role=listbox]\"));\nwatch(\n isOpen,\n (now) => {\n if (now && !quiet.personOpened()) quiet.undoFocusSteal();\n },\n { immediate: true, flush: \"post\" },\n);\nfunction closeFocus(e: Event) {\n if (!quiet.returnsFocus()) e.preventDefault();\n}\nfunction keydown(e: KeyboardEvent) {\n quiet.intent();\n typeahead(e);\n}\nfunction typeahead(e: KeyboardEvent) {\n if (props.disabled || isOpen.value || e.ctrlKey || e.metaKey || e.altKey || e.key.length !== 1) return;\n if (e.key === \" \" && !typed) return;\n const now = Date.now();\n typed = (now - typedAt > 700 ? \"\" : typed) + e.key.toLowerCase();\n typedAt = now;\n const list = props.options;\n const from = list.findIndex((o) => o.value === model.value);\n for (let j = 0; j < list.length; j++) {\n const o = list[(from + j + (typed.length === 1 ? 1 : 0) + list.length) % list.length];\n if (o && !o.disabled && o.label.toLowerCase().startsWith(typed)) {\n model.value = o.value;\n break;\n }\n }\n}\n</script>\n\n<template>\n <div class=\"e-sel\">\n <SelectRoot v-model=\"model\" :open=\"isOpen\" :disabled=\"disabled\" :required=\"required\" @update:open=\"open = $event\">\n <SelectTrigger\n class=\"e-input e-sel-trigger\"\n :tabindex=\"isOpen ? -1 : undefined\"\n v-bind=\"triggerAttrs\"\n @pointerdown=\"quiet.intent\"\n @keydown=\"keydown\"\n >\n <span v-if=\"selected\" class=\"e-sel-value\">\n <EIcon v-if=\"selected.icon\" :name=\"selected.icon\" />{{ selected.label }}\n </span>\n <span v-else class=\"e-sel-placeholder\">{{ placeholder || t(\"select\") }}</span>\n <EIcon name=\"chevron-down\" bold />\n </SelectTrigger>\n <SelectPortal :to=\"portal\">\n <SelectContent\n position=\"popper\"\n align=\"start\"\n :side-offset=\"6\"\n :collision-padding=\"8\"\n :body-lock=\"false\"\n class=\"e-popover e-listpanel e-root\"\n :aria-label=\"label\"\n @close-auto-focus=\"closeFocus\"\n >\n <SelectViewport>\n <template v-for=\"(section, i) in sections\" :key=\"i\">\n <SelectGroup v-if=\"section.group\" class=\"e-opt-set\">\n <SelectLabel class=\"e-opt-group\">{{ section.group }}</SelectLabel>\n <ESelectOption v-for=\"o in section.options\" :key=\"o.value\" :option=\"o\" :selected=\"o.value === model\" />\n </SelectGroup>\n <template v-else>\n <ESelectOption v-for=\"o in section.options\" :key=\"o.value\" :option=\"o\" :selected=\"o.value === model\" />\n </template>\n </template>\n </SelectViewport>\n </SelectContent>\n </SelectPortal>\n </SelectRoot>\n <input v-if=\"name\" type=\"hidden\" :name=\"name\" :value=\"model\" />\n </div>\n</template>\n\n<style>\n@layer e.controls {\n .e-sel {\n position: relative;\n }\n\n .e-sel-trigger {\n display: flex;\n align-items: center;\n justify-content: space-between;\n gap: var(--e-space-2);\n padding-inline-end: var(--e-space-3);\n text-align: start;\n cursor: pointer;\n }\n\n .e-sel-trigger[aria-expanded=\"true\"] {\n border-color: var(--e-ink);\n background-color: var(--e-surface);\n }\n\n .e-sel-value {\n display: inline-flex;\n align-items: center;\n gap: var(--e-space-2);\n min-width: 0;\n overflow: hidden;\n line-height: 1.4;\n text-overflow: ellipsis;\n white-space: nowrap;\n }\n\n .e-sel-placeholder {\n color: var(--e-muted);\n }\n\n .e-sel-trigger > .e-icon {\n flex: none;\n }\n}\n</style>\n"],"mappings":"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"}
1
+ {"version":3,"file":"ESelectControl.vue_vue_type_script_setup_true_lang.js","names":["_useModel","_openBlock","_createElementBlock","_createVNode","_unref","_withCtx","_mergeProps","_createBlock","EIcon","_createCommentVNode","_createTextVNode","_toDisplayString","_Fragment","_renderList","ESelectOption","EIcon_default","ESelectOption_default","_hoisted_1","_hoisted_2","_hoisted_3","_hoisted_4","ESelectControl_vue_vue_type_script_setup_true_lang_default","\"modelValue\"","\"modelModifiers\"","\"open\"","\"openModifiers\"","props","__props","model","useModel","t","useMessages","portal","usePortalTarget","sections","computed","sectionOptions","selected","o","typed","typedAt","open","isOpen","quiet","useQuietFocus","el","now","closeFocus","keydown","typeahead","list","from","j","openBlock","createElementBlock","createVNode","unref","SelectRoot","_cache","$event","withCtx","SelectTrigger","mergeProps","createBlock","createCommentVNode","createTextVNode","toDisplayString","SelectPortal","SelectContent","SelectViewport","Fragment","renderList","i","section","SelectGroup","SelectLabel"],"sources":["../../../src/components/Select/ESelectControl.vue"],"sourcesContent":["<script setup lang=\"ts\">\nimport { computed, watch } from \"vue\";\nimport {\n SelectContent,\n SelectGroup,\n SelectLabel,\n SelectPortal,\n SelectRoot,\n SelectTrigger,\n SelectViewport,\n} from \"reka-ui\";\nimport EIcon from \"../Icon/EIcon.vue\";\nimport ESelectOption from \"./ESelectOption.vue\";\nimport { sectionOptions, type EOption } from \"./options.js\";\nimport { useMessages, usePortalTarget } from \"../../config.js\";\nimport { useQuietFocus } from \"./quietFocus.js\";\nimport \"../../styles/base.css\";\nimport \"../TextField/input.css\";\nimport \"./panel.css\";\n\nconst props = defineProps<{\n /** The normalised options. */\n options: EOption[];\n placeholder?: string | undefined;\n disabled?: boolean | undefined;\n required?: boolean | undefined;\n name?: string | undefined;\n /** Names the list. */\n label?: string | undefined;\n /** Attributes for the button: id, aria-*, data-*, listeners. */\n triggerAttrs: Record<string, unknown>;\n}>();\n\nconst model = defineModel<string>({ default: \"\" });\n\nconst t = useMessages();\nconst portal = usePortalTarget();\n\nconst sections = computed(() => sectionOptions(props.options));\nconst selected = computed(() => props.options.find((o) => o.value === model.value));\n\nlet typed = \"\";\nlet typedAt = 0;\nconst open = defineModel<boolean>(\"open\", { default: false });\nconst isOpen = computed(() => open.value && !props.disabled);\nconst quiet = useQuietFocus(isOpen, (el) => !!el.closest(\"[role=listbox]\"));\nwatch(\n isOpen,\n (now) => {\n if (now && !quiet.personOpened()) quiet.undoFocusSteal();\n },\n { immediate: true, flush: \"post\" },\n);\nfunction closeFocus(e: Event) {\n if (!quiet.returnsFocus()) e.preventDefault();\n}\nfunction keydown(e: KeyboardEvent) {\n quiet.intent();\n typeahead(e);\n}\nfunction typeahead(e: KeyboardEvent) {\n if (props.disabled || isOpen.value || e.ctrlKey || e.metaKey || e.altKey || e.key.length !== 1) return;\n if (e.key === \" \" && !typed) return;\n const now = Date.now();\n typed = (now - typedAt > 700 ? \"\" : typed) + e.key.toLowerCase();\n typedAt = now;\n const list = props.options;\n const from = list.findIndex((o) => o.value === model.value);\n for (let j = 0; j < list.length; j++) {\n const o = list[(from + j + (typed.length === 1 ? 1 : 0) + list.length) % list.length];\n if (o && !o.disabled && o.label.toLowerCase().startsWith(typed)) {\n model.value = o.value;\n break;\n }\n }\n}\n</script>\n\n<template>\n <div class=\"e-sel\">\n <SelectRoot v-model=\"model\" :open=\"isOpen\" :disabled=\"disabled\" :required=\"required\" @update:open=\"open = $event\">\n <SelectTrigger\n class=\"e-input e-sel-trigger\"\n :tabindex=\"isOpen ? -1 : undefined\"\n v-bind=\"triggerAttrs\"\n @pointerdown=\"quiet.intent\"\n @keydown=\"keydown\"\n >\n <span v-if=\"selected\" class=\"e-sel-value\">\n <EIcon v-if=\"selected.icon\" :name=\"selected.icon\" />{{ selected.label }}\n </span>\n <span v-else class=\"e-sel-placeholder\">{{ placeholder || t(\"select\") }}</span>\n <EIcon name=\"chevron-down\" bold />\n </SelectTrigger>\n <SelectPortal :to=\"portal\">\n <SelectContent\n position=\"popper\"\n align=\"start\"\n :side-offset=\"6\"\n :collision-padding=\"8\"\n :body-lock=\"false\"\n class=\"e-popover e-listpanel e-root\"\n :aria-label=\"label\"\n @close-auto-focus=\"closeFocus\"\n >\n <SelectViewport>\n <template v-for=\"(section, i) in sections\" :key=\"i\">\n <SelectGroup v-if=\"section.group\" class=\"e-opt-set\">\n <SelectLabel class=\"e-opt-group\">{{ section.group }}</SelectLabel>\n <ESelectOption v-for=\"o in section.options\" :key=\"o.value\" :option=\"o\" :selected=\"o.value === model\" />\n </SelectGroup>\n <template v-else>\n <ESelectOption v-for=\"o in section.options\" :key=\"o.value\" :option=\"o\" :selected=\"o.value === model\" />\n </template>\n </template>\n </SelectViewport>\n </SelectContent>\n </SelectPortal>\n </SelectRoot>\n <input v-if=\"name\" type=\"hidden\" :name=\"name\" :value=\"model\" />\n </div>\n</template>\n\n<style>\n@layer e.controls {\n .e-sel {\n position: relative;\n }\n\n .e-sel-trigger {\n display: flex;\n align-items: center;\n justify-content: space-between;\n gap: var(--e-space-2);\n padding-inline-end: var(--e-space-3);\n text-align: start;\n cursor: pointer;\n }\n\n .e-sel-trigger[aria-expanded=\"true\"] {\n --e-ring: var(--e-ink);\n\n background-color: var(--e-surface);\n }\n\n .e-sel-value {\n display: inline-flex;\n align-items: center;\n gap: var(--e-space-2);\n min-width: 0;\n overflow: hidden;\n line-height: 1.4;\n text-overflow: ellipsis;\n white-space: nowrap;\n }\n\n .e-sel-placeholder {\n color: var(--e-muted);\n }\n\n .e-sel-trigger > .e-icon {\n flex: none;\n }\n}\n</style>\n"],"mappings":"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"}
@@ -1 +1 @@
1
- {"version":3,"file":"ESignaturePad.js","names":["_sfc_main","ESignaturePad_vue_vue_type_script_setup_true_lang_default","ESignaturePad_default"],"sources":["../../../src/components/SignaturePad/ESignaturePad.vue"],"sourcesContent":["<script setup lang=\"ts\">\nimport { onMounted, ref, watch } from \"vue\";\nimport { useResizeObserver } from \"@vueuse/core\";\nimport EIcon from \"../Icon/EIcon.vue\";\nimport EButton from \"../Button/EButton.vue\";\nimport { useMessages } from \"../../config.js\";\nimport { useUid } from \"../../composables/useUid.js\";\nimport \"../../styles/base.css\";\n\nconst props = withDefaults(\n defineProps<{\n /** The height of the drawing area in pixels. */\n height?: number;\n /** Ignores drawing and disables Clear. */\n disabled?: boolean;\n /** The id of the canvas. @default generated */\n id?: string;\n }>(),\n { height: 160 },\n);\n\n/** A PNG data URL (black on transparent); empty while clear. Set `\"\"` to clear. */\nconst model = defineModel<string>({ default: \"\" });\n\nconst t = useMessages();\nconst id = useUid(() => props.id);\nconst canvas = ref<HTMLCanvasElement | null>(null);\nconst empty = ref(!model.value);\n\ninterface Point {\n x: number;\n y: number;\n}\nconst strokes: Point[][] = [];\nlet current: Point[] | null = null;\n\nfunction paint(ctx: CanvasRenderingContext2D, color: string) {\n ctx.lineWidth = 2.5;\n ctx.lineCap = \"round\";\n ctx.lineJoin = \"round\";\n ctx.strokeStyle = color;\n ctx.fillStyle = color;\n for (const stroke of strokes) {\n const [first, ...rest] = stroke;\n if (!first) continue;\n ctx.beginPath();\n ctx.arc(first.x, first.y, 1.2, 0, 6.3);\n ctx.fill();\n ctx.beginPath();\n ctx.moveTo(first.x, first.y);\n for (const p of rest) ctx.lineTo(p.x, p.y);\n ctx.stroke();\n }\n}\n\nfunction setup() {\n const cv = canvas.value;\n if (!cv) return;\n const dpr = window.devicePixelRatio || 1;\n cv.width = Math.round((cv.clientWidth || 320) * dpr);\n cv.height = Math.round(props.height * dpr);\n const ctx = cv.getContext(\"2d\");\n if (!ctx) return;\n ctx.scale(dpr, dpr);\n paint(ctx, getComputedStyle(cv).color);\n}\nonMounted(setup);\nuseResizeObserver(canvas, setup);\n\nfunction point(e: PointerEvent): Point {\n const r = canvas.value!.getBoundingClientRect();\n return { x: e.clientX - r.left, y: e.clientY - r.top };\n}\n\nfunction down(e: PointerEvent) {\n if (props.disabled) return;\n e.preventDefault();\n try {\n canvas.value!.setPointerCapture(e.pointerId);\n } catch {}\n const p = point(e);\n current = [p];\n strokes.push(current);\n const ctx = canvas.value!.getContext(\"2d\")!;\n ctx.fillStyle = getComputedStyle(canvas.value!).color;\n ctx.beginPath();\n ctx.arc(p.x, p.y, 1.2, 0, 6.3);\n ctx.fill();\n}\n\nfunction move(e: PointerEvent) {\n if (!current) return;\n const from = current[current.length - 1]!;\n const p = point(e);\n current.push(p);\n const ctx = canvas.value!.getContext(\"2d\")!;\n ctx.strokeStyle = getComputedStyle(canvas.value!).color;\n ctx.beginPath();\n ctx.moveTo(from.x, from.y);\n ctx.lineTo(p.x, p.y);\n ctx.stroke();\n}\n\nfunction exportImage(): string {\n const cv = canvas.value!;\n const out = document.createElement(\"canvas\");\n out.width = cv.width;\n out.height = cv.height;\n const ctx = out.getContext(\"2d\")!;\n ctx.scale(cv.width / (cv.clientWidth || 320), cv.height / props.height);\n paint(ctx, \"black\");\n return out.toDataURL(\"image/png\");\n}\n\nfunction up() {\n if (!current) return;\n current = null;\n empty.value = false;\n model.value = exportImage();\n}\n\nfunction wipe() {\n strokes.length = 0;\n current = null;\n empty.value = true;\n const cv = canvas.value;\n const ctx = cv?.getContext(\"2d\");\n if (cv && ctx) {\n ctx.save();\n ctx.setTransform(1, 0, 0, 1, 0, 0);\n ctx.clearRect(0, 0, cv.width, cv.height);\n ctx.restore();\n }\n}\n\nfunction clear() {\n wipe();\n model.value = \"\";\n}\n\nwatch(model, (v) => {\n if (!v && !empty.value) wipe();\n});\n\ndefineExpose({\n clear,\n canvas,\n});\n</script>\n\n<template>\n <div class=\"e-pad\">\n <div class=\"e-pad-surface\" :data-empty=\"empty ? '' : undefined\">\n <canvas\n :id=\"id\"\n ref=\"canvas\"\n class=\"e-pad-canvas\"\n role=\"img\"\n :style=\"{ height: `${height}px`, color: 'var(--e-ink)' }\"\n :aria-label=\"t('drawSignature')\"\n :aria-describedby=\"`${id}-hint`\"\n @pointerdown=\"down\"\n @pointermove=\"move\"\n @pointerup=\"up\"\n @pointercancel=\"up\"\n />\n <span v-if=\"empty\" class=\"e-pad-placeholder\" aria-hidden=\"true\">\n <EIcon name=\"signature\" />\n {{ t(\"signEmpty\") }}\n </span>\n </div>\n <div class=\"e-pad-foot\">\n <p :id=\"`${id}-hint`\" class=\"e-field-hint\">{{ t(\"signDrawHint\") }}</p>\n <EButton variant=\"quiet\" icon=\"eraser\" :disabled=\"empty || disabled\" @click=\"clear\">\n {{ t(\"signClear\") }}\n </EButton>\n </div>\n </div>\n</template>\n\n<style>\n@layer e.composites {\n .e-pad {\n display: grid;\n gap: var(--e-space-2);\n }\n\n .e-pad-surface {\n position: relative;\n overflow: hidden;\n border: var(--e-stroke-edge) solid var(--e-border-strong);\n border-radius: var(--e-radius-md);\n background: var(--e-surface);\n box-shadow: var(--e-well);\n }\n\n .e-pad-surface::after {\n content: \"\";\n position: absolute;\n inset-inline: var(--e-space-4);\n bottom: 36px;\n border-bottom: var(--e-stroke-edge) solid var(--e-ink);\n pointer-events: none;\n }\n\n .e-pad-canvas {\n display: block;\n width: 100%;\n touch-action: none;\n cursor: crosshair;\n }\n\n .e-pad-placeholder {\n position: absolute;\n inset: 0;\n display: grid;\n place-content: center;\n justify-items: center;\n gap: var(--e-space-2);\n color: var(--e-muted);\n font: 400 var(--e-text-sm)/1.4 var(--e-font-sans);\n pointer-events: none;\n }\n\n .e-pad-foot {\n display: flex;\n flex-wrap: wrap;\n align-items: center;\n justify-content: space-between;\n gap: var(--e-space-2) var(--e-space-4);\n }\n\n .e-pad-foot .e-field-hint {\n margin: 0;\n flex: 1 1 14rem;\n }\n}\n</style>\n"],"mappings":""}
1
+ {"version":3,"file":"ESignaturePad.js","names":["_sfc_main","ESignaturePad_vue_vue_type_script_setup_true_lang_default","ESignaturePad_default"],"sources":["../../../src/components/SignaturePad/ESignaturePad.vue"],"sourcesContent":["<script setup lang=\"ts\">\nimport { onMounted, ref, watch } from \"vue\";\nimport { useResizeObserver } from \"@vueuse/core\";\nimport EIcon from \"../Icon/EIcon.vue\";\nimport EButton from \"../Button/EButton.vue\";\nimport { useMessages } from \"../../config.js\";\nimport { useUid } from \"../../composables/useUid.js\";\nimport \"../../styles/base.css\";\n\nconst props = withDefaults(\n defineProps<{\n /** The height of the drawing area in pixels. */\n height?: number;\n /** Ignores drawing and disables Clear. */\n disabled?: boolean;\n /** The id of the canvas. @default generated */\n id?: string;\n }>(),\n { height: 160 },\n);\n\n/** A PNG data URL (black on transparent); empty while clear. Set `\"\"` to clear. */\nconst model = defineModel<string>({ default: \"\" });\n\nconst t = useMessages();\nconst id = useUid(() => props.id);\nconst canvas = ref<HTMLCanvasElement | null>(null);\nconst empty = ref(!model.value);\n\ninterface Point {\n x: number;\n y: number;\n}\nconst strokes: Point[][] = [];\nlet current: Point[] | null = null;\n\nfunction paint(ctx: CanvasRenderingContext2D, color: string) {\n ctx.lineWidth = 2.5;\n ctx.lineCap = \"round\";\n ctx.lineJoin = \"round\";\n ctx.strokeStyle = color;\n ctx.fillStyle = color;\n for (const stroke of strokes) {\n const [first, ...rest] = stroke;\n if (!first) continue;\n ctx.beginPath();\n ctx.arc(first.x, first.y, 1.2, 0, 6.3);\n ctx.fill();\n ctx.beginPath();\n ctx.moveTo(first.x, first.y);\n for (const p of rest) ctx.lineTo(p.x, p.y);\n ctx.stroke();\n }\n}\n\nfunction setup() {\n const cv = canvas.value;\n if (!cv) return;\n const dpr = window.devicePixelRatio || 1;\n cv.width = Math.round((cv.clientWidth || 320) * dpr);\n cv.height = Math.round(props.height * dpr);\n const ctx = cv.getContext(\"2d\");\n if (!ctx) return;\n ctx.scale(dpr, dpr);\n paint(ctx, getComputedStyle(cv).color);\n}\nonMounted(setup);\nuseResizeObserver(canvas, setup);\n\nfunction point(e: PointerEvent): Point {\n const r = canvas.value!.getBoundingClientRect();\n return { x: e.clientX - r.left, y: e.clientY - r.top };\n}\n\nfunction down(e: PointerEvent) {\n if (props.disabled) return;\n e.preventDefault();\n try {\n canvas.value!.setPointerCapture(e.pointerId);\n } catch {}\n const p = point(e);\n current = [p];\n strokes.push(current);\n const ctx = canvas.value!.getContext(\"2d\")!;\n ctx.fillStyle = getComputedStyle(canvas.value!).color;\n ctx.beginPath();\n ctx.arc(p.x, p.y, 1.2, 0, 6.3);\n ctx.fill();\n}\n\nfunction move(e: PointerEvent) {\n if (!current) return;\n const from = current[current.length - 1]!;\n const p = point(e);\n current.push(p);\n const ctx = canvas.value!.getContext(\"2d\")!;\n ctx.strokeStyle = getComputedStyle(canvas.value!).color;\n ctx.beginPath();\n ctx.moveTo(from.x, from.y);\n ctx.lineTo(p.x, p.y);\n ctx.stroke();\n}\n\nfunction exportImage(): string {\n const cv = canvas.value!;\n const out = document.createElement(\"canvas\");\n out.width = cv.width;\n out.height = cv.height;\n const ctx = out.getContext(\"2d\")!;\n ctx.scale(cv.width / (cv.clientWidth || 320), cv.height / props.height);\n paint(ctx, \"black\");\n return out.toDataURL(\"image/png\");\n}\n\nfunction up() {\n if (!current) return;\n current = null;\n empty.value = false;\n model.value = exportImage();\n}\n\nfunction wipe() {\n strokes.length = 0;\n current = null;\n empty.value = true;\n const cv = canvas.value;\n const ctx = cv?.getContext(\"2d\");\n if (cv && ctx) {\n ctx.save();\n ctx.setTransform(1, 0, 0, 1, 0, 0);\n ctx.clearRect(0, 0, cv.width, cv.height);\n ctx.restore();\n }\n}\n\nfunction clear() {\n wipe();\n model.value = \"\";\n}\n\nwatch(model, (v) => {\n if (!v && !empty.value) wipe();\n});\n\ndefineExpose({\n clear,\n canvas,\n});\n</script>\n\n<template>\n <div class=\"e-pad\">\n <div class=\"e-pad-surface\" :data-empty=\"empty ? '' : undefined\">\n <canvas\n :id=\"id\"\n ref=\"canvas\"\n class=\"e-pad-canvas\"\n role=\"img\"\n :style=\"{ height: `${height}px`, color: 'var(--e-ink)' }\"\n :aria-label=\"t('drawSignature')\"\n :aria-describedby=\"`${id}-hint`\"\n @pointerdown=\"down\"\n @pointermove=\"move\"\n @pointerup=\"up\"\n @pointercancel=\"up\"\n />\n <span v-if=\"empty\" class=\"e-pad-placeholder\" aria-hidden=\"true\">\n <EIcon name=\"signature\" />\n {{ t(\"signEmpty\") }}\n </span>\n </div>\n <div class=\"e-pad-foot\">\n <p :id=\"`${id}-hint`\" class=\"e-field-hint\">{{ t(\"signDrawHint\") }}</p>\n <EButton variant=\"quiet\" icon=\"eraser\" :disabled=\"empty || disabled\" @click=\"clear\">\n {{ t(\"signClear\") }}\n </EButton>\n </div>\n </div>\n</template>\n\n<style>\n@layer e.composites {\n .e-pad {\n display: grid;\n gap: var(--e-space-2);\n }\n\n .e-pad-surface {\n position: relative;\n overflow: hidden;\n border-radius: var(--e-radius-md);\n background: var(--e-surface);\n box-shadow:\n inset 0 0 0 var(--e-stroke-edge) var(--e-border-strong),\n var(--e-well);\n }\n\n .e-pad-surface::after {\n content: \"\";\n position: absolute;\n inset-inline: var(--e-space-4);\n bottom: 36px;\n border-bottom: var(--e-stroke-edge) solid var(--e-ink);\n pointer-events: none;\n }\n\n .e-pad-canvas {\n display: block;\n width: 100%;\n touch-action: none;\n cursor: crosshair;\n }\n\n .e-pad-placeholder {\n position: absolute;\n inset: 0;\n display: grid;\n place-content: center;\n justify-items: center;\n gap: var(--e-space-2);\n color: var(--e-muted);\n font: 400 var(--e-text-sm)/1.4 var(--e-font-sans);\n pointer-events: none;\n }\n\n .e-pad-foot {\n display: flex;\n flex-wrap: wrap;\n align-items: center;\n justify-content: space-between;\n gap: var(--e-space-2) var(--e-space-4);\n }\n\n .e-pad-foot .e-field-hint {\n margin: 0;\n flex: 1 1 14rem;\n }\n}\n</style>\n"],"mappings":""}