@eos-ui/vue 0.3.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 (108) 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/CodeBlock/ECodeBlock.js.map +1 -1
  21. package/dist/components/CodeBlock/ECodeBlock.vue_vue_type_script_setup_true_lang.js.map +1 -1
  22. package/dist/components/Combobox/EComboboxBase.js.map +1 -1
  23. package/dist/components/Combobox/EComboboxBase.vue_vue_type_script_setup_true_lang.js +4 -8
  24. package/dist/components/Combobox/EComboboxBase.vue_vue_type_script_setup_true_lang.js.map +1 -1
  25. package/dist/components/Combobox/types.d.ts +2 -2
  26. package/dist/components/DataGrid/EDataGrid.js.map +1 -1
  27. package/dist/components/DataGrid/EDataGrid.vue.d.ts +1 -1
  28. package/dist/components/DataGrid/EDataGrid.vue_vue_type_script_setup_true_lang.js +1 -0
  29. package/dist/components/DataGrid/EDataGrid.vue_vue_type_script_setup_true_lang.js.map +1 -1
  30. package/dist/components/DescriptionList/EDescriptionList.js.map +1 -1
  31. package/dist/components/DescriptionList/EDescriptionList.vue_vue_type_script_setup_true_lang.js +2 -2
  32. package/dist/components/DescriptionList/EDescriptionList.vue_vue_type_script_setup_true_lang.js.map +1 -1
  33. package/dist/components/Dialog/EDialog.js.map +1 -1
  34. package/dist/components/Dialog/EDialog.vue_vue_type_script_setup_true_lang.js.map +1 -1
  35. package/dist/components/Drawer/EDrawer.js.map +1 -1
  36. package/dist/components/Drawer/EDrawer.vue_vue_type_script_setup_true_lang.js.map +1 -1
  37. package/dist/components/EmptyState/EEmptyState.js.map +1 -1
  38. package/dist/components/EmptyState/EEmptyState.vue.d.ts +1 -1
  39. package/dist/components/EmptyState/EEmptyState.vue_vue_type_script_setup_true_lang.js.map +1 -1
  40. package/dist/components/ExpandableRow/EExpandableRow.js.map +1 -1
  41. package/dist/components/ExpandableRow/EExpandableRow.vue_vue_type_script_setup_true_lang.js.map +1 -1
  42. package/dist/components/Grid/EGrid.js.map +1 -1
  43. package/dist/components/Grid/EGrid.vue.d.ts +1 -1
  44. package/dist/components/Grid/EGrid.vue_vue_type_script_setup_true_lang.js.map +1 -1
  45. package/dist/components/IconButton/EIconButton.js.map +1 -1
  46. package/dist/components/IconButton/EIconButton.vue_vue_type_script_setup_true_lang.js.map +1 -1
  47. package/dist/components/Inline/EInline.js.map +1 -1
  48. package/dist/components/Inline/EInline.vue.d.ts +1 -1
  49. package/dist/components/Inline/EInline.vue_vue_type_script_setup_true_lang.js.map +1 -1
  50. package/dist/components/Kbd/EKbd.js.map +1 -1
  51. package/dist/components/Kbd/EKbd.vue_vue_type_script_setup_true_lang.js.map +1 -1
  52. package/dist/components/Menu/EMenu.js.map +1 -1
  53. package/dist/components/Menu/EMenu.vue_vue_type_script_setup_true_lang.js.map +1 -1
  54. package/dist/components/NavList/ENavList.js.map +1 -1
  55. package/dist/components/NavList/ENavList.vue_vue_type_script_setup_true_lang.js.map +1 -1
  56. package/dist/components/Notice/ENotice.js.map +1 -1
  57. package/dist/components/Notice/ENotice.vue_vue_type_script_setup_true_lang.js.map +1 -1
  58. package/dist/components/OtpField/EOtpField.js.map +1 -1
  59. package/dist/components/OtpField/EOtpField.vue_vue_type_script_setup_true_lang.js.map +1 -1
  60. package/dist/components/Pagination/EPagination.js.map +1 -1
  61. package/dist/components/Pagination/EPagination.vue_vue_type_script_setup_true_lang.js.map +1 -1
  62. package/dist/components/PasswordField/EPasswordField.js.map +1 -1
  63. package/dist/components/PasswordField/EPasswordField.vue_vue_type_script_setup_true_lang.js.map +1 -1
  64. package/dist/components/Progress/EProgress.js.map +1 -1
  65. package/dist/components/Progress/EProgress.vue_vue_type_script_setup_true_lang.js.map +1 -1
  66. package/dist/components/SearchBar/ESearchBar.js.map +1 -1
  67. package/dist/components/SearchBar/ESearchBar.vue.d.ts +1 -1
  68. package/dist/components/SearchBar/ESearchBar.vue_vue_type_script_setup_true_lang.js.map +1 -1
  69. package/dist/components/SearchResults/ESearchResults.js.map +1 -1
  70. package/dist/components/SearchResults/ESearchResults.vue_vue_type_script_setup_true_lang.js.map +1 -1
  71. package/dist/components/Segmented/ESegmented.js.map +1 -1
  72. package/dist/components/Segmented/ESegmented.vue_vue_type_script_setup_true_lang.js.map +1 -1
  73. package/dist/components/Select/ESelectControl.js.map +1 -1
  74. package/dist/components/Select/ESelectControl.vue_vue_type_script_setup_true_lang.js.map +1 -1
  75. package/dist/components/SignaturePad/ESignaturePad.js.map +1 -1
  76. package/dist/components/SignaturePad/ESignaturePad.vue_vue_type_script_setup_true_lang.js.map +1 -1
  77. package/dist/components/Skeleton/ESkeleton.js.map +1 -1
  78. package/dist/components/Skeleton/ESkeleton.vue_vue_type_script_setup_true_lang.js.map +1 -1
  79. package/dist/components/Stack/EStack.js.map +1 -1
  80. package/dist/components/Stack/EStack.vue.d.ts +1 -1
  81. package/dist/components/Stack/EStack.vue_vue_type_script_setup_true_lang.js.map +1 -1
  82. package/dist/components/Stamp/EStamp.js.map +1 -1
  83. package/dist/components/Stamp/EStamp.vue.d.ts +2 -2
  84. package/dist/components/Stamp/EStamp.vue_vue_type_script_setup_true_lang.js +2 -2
  85. package/dist/components/Stamp/EStamp.vue_vue_type_script_setup_true_lang.js.map +1 -1
  86. package/dist/components/Stepper/EStepper.js.map +1 -1
  87. package/dist/components/Stepper/EStepper.vue_vue_type_script_setup_true_lang.js.map +1 -1
  88. package/dist/components/Surface/ESurface.js.map +1 -1
  89. package/dist/components/Surface/ESurface.vue.d.ts +1 -1
  90. package/dist/components/Surface/ESurface.vue_vue_type_script_setup_true_lang.js.map +1 -1
  91. package/dist/components/Switch/ESwitch.js.map +1 -1
  92. package/dist/components/Switch/ESwitch.vue_vue_type_script_setup_true_lang.js.map +1 -1
  93. package/dist/components/Table/ETable.js +8 -0
  94. package/dist/components/Table/ETable.js.map +1 -0
  95. package/dist/components/Table/ETable.vue.d.ts +25 -0
  96. package/dist/components/Table/ETable.vue_vue_type_script_setup_true_lang.js +28 -0
  97. package/dist/components/Table/ETable.vue_vue_type_script_setup_true_lang.js.map +1 -0
  98. package/dist/components/Table/index.d.ts +1 -0
  99. package/dist/components/Tabs/ETabs.js.map +1 -1
  100. package/dist/components/Tabs/ETabs.vue.d.ts +10 -2
  101. package/dist/components/Tabs/ETabs.vue_vue_type_script_setup_true_lang.js +11 -3
  102. package/dist/components/Tabs/ETabs.vue_vue_type_script_setup_true_lang.js.map +1 -1
  103. package/dist/components/Upload/EUpload.js.map +1 -1
  104. package/dist/components/Upload/EUpload.vue_vue_type_script_setup_true_lang.js.map +1 -1
  105. package/dist/index.d.ts +1 -0
  106. package/dist/index.js +10 -9
  107. package/dist/style.css +572 -364
  108. package/package.json +3 -2
@@ -1 +1 @@
1
- {"version":3,"file":"ENavList.js","names":["_sfc_main","ENavList_vue_vue_type_script_setup_true_lang_default","ENavList_default"],"sources":["../../../src/components/NavList/ENavList.vue"],"sourcesContent":["<script setup lang=\"ts\">\nimport { computed, type Component } from \"vue\";\nimport EIcon from \"../Icon/EIcon.vue\";\nimport LinkNav, { type LinkItem, type LinkSection } from \"./LinkNav.vue\";\nimport type { IconProp } from \"../../icons/types.js\";\nimport \"../../styles/base.css\";\n\nexport interface NavItem extends LinkItem {\n /** An icon before the label. */\n icon?: IconProp;\n /** A count of things waiting on the person (bills to pay, forms to sign). */\n count?: number;\n}\n\nexport type NavSection = LinkSection<NavItem>;\n\nconst props = withDefaults(\n defineProps<{\n /** The destinations, in order: `{ label, href?, to?, icon?, count?, current? }`. With no `href` or `to` a link goes to `#`. Set `current` yourself. */\n items?: NavItem[];\n /** Destinations in labelled groups, instead of `items`: `{ label?, items }`. Give a label only when there is more than one section. */\n sections?: NavSection[];\n /** `vertical` stacks the links, for a sidebar or a menu. `horizontal` lays them in a row, for a header, with a hairline between each. Items look the same as in the vertical list: a tint on hover, and a primary outline with a heavier bottom edge on the current page. */\n orientation?: \"vertical\" | \"horizontal\";\n /** The landmark's name; give each navigation on a page its own. @default \"Main\" */\n label?: string;\n /** What renders each link: `\"a\"` by default, or `RouterLink` (or any component that takes `href` or `to` and a default slot). Give items `to`; it receives `to` or `href`, the class `e-nav-item` and `aria-current`. */\n linkComponent?: string | Component;\n }>(),\n { orientation: \"vertical\", linkComponent: \"a\" },\n);\n\nconst groups = computed<NavSection[]>(() => props.sections ?? [{ items: props.items ?? [] }]);\n</script>\n\n<template>\n <LinkNav\n class=\"e-nav\"\n :class=\"orientation === 'horizontal' && 'e-nav--horizontal'\"\n :groups=\"groups\"\n :label=\"label\"\n :link-component=\"linkComponent\"\n item-class=\"e-nav-item\"\n heading-class=\"e-nav-heading\"\n >\n <template #item=\"{ item }\">\n <EIcon v-if=\"item.icon\" :name=\"item.icon\" />\n <span class=\"e-nav-label\">{{ item.label }}</span>\n <span v-if=\"item.count != null\" class=\"e-nav-count\">{{ item.count }}</span>\n </template>\n </LinkNav>\n</template>\n\n<style>\n@layer e.page {\n .e-nav ul {\n display: grid;\n gap: calc(var(--e-space-1) / 2);\n margin: 0;\n padding: 0;\n list-style: none;\n }\n\n .e-nav:not(.e-nav--horizontal) ul {\n gap: 0;\n }\n\n .e-nav:not(.e-nav--horizontal) li + li::before {\n content: \"\";\n display: block;\n height: var(--e-stroke-hair);\n margin-block: var(--e-space-2);\n background: color-mix(in srgb, var(--e-border) 60%, transparent);\n }\n\n .e-nav-item {\n display: flex;\n align-items: center;\n gap: var(--e-space-3);\n height: var(--e-control-height);\n box-sizing: border-box;\n padding: 0 var(--e-space-3);\n border: var(--e-stroke-edge) solid transparent;\n border-radius: var(--e-radius-md);\n color: var(--e-ink);\n font: 400 var(--e-text-md) / 1 var(--e-font-sans);\n text-decoration: none;\n transition: background-color var(--e-duration-tap) var(--e-easing-out);\n }\n\n .e-nav-item:hover {\n background: var(--e-surface-hover);\n }\n\n .e-nav-item:focus-visible {\n outline: var(--e-stroke-focus) solid var(--e-focus-ring);\n outline-offset: var(--e-focus-gap);\n }\n\n .e-nav-item[aria-current=\"page\"] {\n background: color-mix(in srgb, var(--e-surface-tint), var(--e-ink) 3%);\n font-weight: 600;\n border-color: var(--e-primary);\n border-bottom-width: calc(var(--e-stroke-edge) + var(--e-depth));\n }\n\n .e-nav-label {\n flex: 1;\n min-width: 0;\n }\n\n .e-nav--horizontal {\n display: flex;\n flex-wrap: wrap;\n align-items: center;\n gap: var(--e-space-2) var(--e-space-4);\n }\n\n /* The separator sits inside the next item's li, so the list has no gap of its own: the margins on the separator space both sides equally. */\n .e-nav--horizontal ul {\n display: flex;\n flex-wrap: wrap;\n gap: 0;\n }\n\n .e-nav--horizontal li {\n display: flex;\n align-items: center;\n }\n\n .e-nav--horizontal li + li::before {\n content: \"\";\n width: var(--e-stroke-hair);\n height: 1.75rem;\n margin-inline: var(--e-space-2);\n background: color-mix(in srgb, var(--e-border) 60%, transparent);\n }\n\n .e-nav--horizontal .e-nav-heading {\n margin: 0;\n padding-inline: 0;\n }\n\n .e-nav-count {\n min-width: var(--e-space-6);\n padding: 0 var(--e-space-2);\n border-radius: var(--e-radius-pill);\n background: color-mix(in srgb, var(--e-primary) 12%, var(--e-surface));\n box-shadow: inset 0 0 0 var(--e-stroke-hair) var(--e-primary);\n outline: var(--e-stroke-hair) solid var(--e-primary);\n outline-offset: calc(-1 * var(--e-stroke-hair));\n font: 600 var(--e-text-xs) / 20px var(--e-font-mono);\n text-align: center;\n }\n\n @media (prefers-reduced-motion: reduce) {\n .e-nav-item {\n transition: none;\n }\n }\n\n @media (forced-colors: active) {\n .e-nav-item[aria-current=\"page\"] {\n border-color: Highlight;\n }\n }\n}\n</style>\n"],"mappings":""}
1
+ {"version":3,"file":"ENavList.js","names":["_sfc_main","ENavList_vue_vue_type_script_setup_true_lang_default","ENavList_default"],"sources":["../../../src/components/NavList/ENavList.vue"],"sourcesContent":["<script setup lang=\"ts\">\nimport { computed, type Component } from \"vue\";\nimport EIcon from \"../Icon/EIcon.vue\";\nimport LinkNav, { type LinkItem, type LinkSection } from \"./LinkNav.vue\";\nimport type { IconProp } from \"../../icons/types.js\";\nimport \"../../styles/base.css\";\n\nexport interface NavItem extends LinkItem {\n /** An icon before the label. */\n icon?: IconProp;\n /** A count of things waiting on the person (bills to pay, forms to sign). */\n count?: number;\n}\n\nexport type NavSection = LinkSection<NavItem>;\n\nconst props = withDefaults(\n defineProps<{\n /** The destinations, in order: `{ label, href?, to?, icon?, count?, current? }`. With no `href` or `to` a link goes to `#`. Set `current` yourself. */\n items?: NavItem[];\n /** Destinations in labelled groups, instead of `items`: `{ label?, items }`. Give a label only when there is more than one section. */\n sections?: NavSection[];\n /** `vertical` stacks the links, for a sidebar or a menu. `horizontal` lays them in a row, for a header, with a hairline between each. Items look the same as in the vertical list: a tint on hover, and a primary outline with a heavier bottom edge on the current page. */\n orientation?: \"vertical\" | \"horizontal\";\n /** The landmark's name; give each navigation on a page its own. @default \"Main\" */\n label?: string;\n /** What renders each link: `\"a\"` by default, or `RouterLink` (or any component that takes `href` or `to` and a default slot). Give items `to`; it receives `to` or `href`, the class `e-nav-item` and `aria-current`. */\n linkComponent?: string | Component;\n }>(),\n { orientation: \"vertical\", linkComponent: \"a\" },\n);\n\nconst groups = computed<NavSection[]>(() => props.sections ?? [{ items: props.items ?? [] }]);\n</script>\n\n<template>\n <LinkNav\n class=\"e-nav\"\n :class=\"orientation === 'horizontal' && 'e-nav--horizontal'\"\n :groups=\"groups\"\n :label=\"label\"\n :link-component=\"linkComponent\"\n item-class=\"e-nav-item\"\n heading-class=\"e-nav-heading\"\n >\n <template #item=\"{ item }\">\n <EIcon v-if=\"item.icon\" :name=\"item.icon\" />\n <span class=\"e-nav-label\">{{ item.label }}</span>\n <span v-if=\"item.count != null\" class=\"e-nav-count\">{{ item.count }}</span>\n </template>\n </LinkNav>\n</template>\n\n<style>\n@layer e.page {\n .e-nav ul {\n display: grid;\n gap: calc(var(--e-space-1) / 2);\n margin: 0;\n padding: 0;\n list-style: none;\n }\n\n .e-nav:not(.e-nav--horizontal) ul {\n gap: 0;\n }\n\n .e-nav:not(.e-nav--horizontal) li + li::before {\n content: \"\";\n display: block;\n height: var(--e-stroke-hair);\n margin-block: var(--e-space-2);\n background: color-mix(in srgb, var(--e-border) 60%, transparent);\n }\n\n .e-nav-item {\n display: flex;\n align-items: center;\n gap: var(--e-space-3);\n height: var(--e-control-height);\n box-sizing: border-box;\n padding: 0 var(--e-space-3) var(--e-lift);\n\n --e-lift: 0px;\n\n border: 0;\n border-radius: var(--e-radius-md);\n color: var(--e-ink);\n font: 400 var(--e-text-md) / 1 var(--e-font-sans);\n text-decoration: none;\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-nav-item:hover {\n background-color: var(--e-surface-hover);\n }\n\n .e-nav-item:focus-visible {\n outline: var(--e-stroke-focus) solid var(--e-focus-ring);\n outline-offset: var(--e-focus-gap);\n }\n\n .e-nav-item[aria-current=\"page\"] {\n background-color: color-mix(in srgb, var(--e-surface-tint), var(--e-ink) 3%);\n font-weight: 600;\n\n --e-lift: var(--e-depth);\n --e-slab: var(--e-primary);\n\n box-shadow:\n inset 0 0 0 var(--e-stroke-edge) var(--e-primary),\n inset 0 calc(-1 * (var(--e-lift) + var(--e-stroke-edge))) 0 0 var(--e-slab);\n }\n\n .e-nav-item[aria-current=\"page\"]:hover {\n --e-slab: color-mix(in srgb, var(--e-primary), var(--e-shade-slab));\n }\n\n .e-nav-label {\n flex: 1;\n min-width: 0;\n }\n\n .e-nav--horizontal {\n display: flex;\n flex-wrap: wrap;\n align-items: center;\n gap: var(--e-space-2) var(--e-space-4);\n }\n\n /* The separator sits inside the next item's li, so the list has no gap of its own: the margins on the separator space both sides equally. */\n .e-nav--horizontal ul {\n display: flex;\n flex-wrap: wrap;\n gap: 0;\n }\n\n .e-nav--horizontal li {\n display: flex;\n align-items: center;\n }\n\n .e-nav--horizontal li + li::before {\n content: \"\";\n width: var(--e-stroke-hair);\n height: 1.75rem;\n margin-inline: var(--e-space-2);\n background: color-mix(in srgb, var(--e-border) 60%, transparent);\n }\n\n .e-nav--horizontal .e-nav-heading {\n margin: 0;\n padding-inline: 0;\n }\n\n .e-nav-count {\n min-width: var(--e-space-6);\n padding: 0 var(--e-space-2);\n border-radius: var(--e-radius-pill);\n background: color-mix(in srgb, var(--e-primary) 12%, var(--e-surface));\n box-shadow: inset 0 0 0 var(--e-stroke-hair) var(--e-primary);\n font: 600 var(--e-text-xs) / 20px var(--e-font-mono);\n text-align: center;\n }\n\n @media (prefers-reduced-motion: reduce) {\n .e-nav-item {\n transition: none;\n }\n }\n\n @media (forced-colors: active) {\n .e-nav-item[aria-current=\"page\"] {\n border-color: Highlight;\n }\n }\n}\n</style>\n"],"mappings":""}
@@ -1 +1 @@
1
- {"version":3,"file":"ENavList.vue_vue_type_script_setup_true_lang.js","names":["_openBlock","_createBlock","LinkNav","_normalizeClass","_withCtx","EIcon","_createCommentVNode","_createElementVNode","_toDisplayString","_createElementBlock","EIcon_default","LinkNav_default","_hoisted_1","_hoisted_2","ENavList_vue_vue_type_script_setup_true_lang_default","props","__props","groups","computed","openBlock","createBlock","normalizeClass","withCtx","item","createCommentVNode","createElementVNode","toDisplayString","createElementBlock"],"sources":["../../../src/components/NavList/ENavList.vue"],"sourcesContent":["<script setup lang=\"ts\">\nimport { computed, type Component } from \"vue\";\nimport EIcon from \"../Icon/EIcon.vue\";\nimport LinkNav, { type LinkItem, type LinkSection } from \"./LinkNav.vue\";\nimport type { IconProp } from \"../../icons/types.js\";\nimport \"../../styles/base.css\";\n\nexport interface NavItem extends LinkItem {\n /** An icon before the label. */\n icon?: IconProp;\n /** A count of things waiting on the person (bills to pay, forms to sign). */\n count?: number;\n}\n\nexport type NavSection = LinkSection<NavItem>;\n\nconst props = withDefaults(\n defineProps<{\n /** The destinations, in order: `{ label, href?, to?, icon?, count?, current? }`. With no `href` or `to` a link goes to `#`. Set `current` yourself. */\n items?: NavItem[];\n /** Destinations in labelled groups, instead of `items`: `{ label?, items }`. Give a label only when there is more than one section. */\n sections?: NavSection[];\n /** `vertical` stacks the links, for a sidebar or a menu. `horizontal` lays them in a row, for a header, with a hairline between each. Items look the same as in the vertical list: a tint on hover, and a primary outline with a heavier bottom edge on the current page. */\n orientation?: \"vertical\" | \"horizontal\";\n /** The landmark's name; give each navigation on a page its own. @default \"Main\" */\n label?: string;\n /** What renders each link: `\"a\"` by default, or `RouterLink` (or any component that takes `href` or `to` and a default slot). Give items `to`; it receives `to` or `href`, the class `e-nav-item` and `aria-current`. */\n linkComponent?: string | Component;\n }>(),\n { orientation: \"vertical\", linkComponent: \"a\" },\n);\n\nconst groups = computed<NavSection[]>(() => props.sections ?? [{ items: props.items ?? [] }]);\n</script>\n\n<template>\n <LinkNav\n class=\"e-nav\"\n :class=\"orientation === 'horizontal' && 'e-nav--horizontal'\"\n :groups=\"groups\"\n :label=\"label\"\n :link-component=\"linkComponent\"\n item-class=\"e-nav-item\"\n heading-class=\"e-nav-heading\"\n >\n <template #item=\"{ item }\">\n <EIcon v-if=\"item.icon\" :name=\"item.icon\" />\n <span class=\"e-nav-label\">{{ item.label }}</span>\n <span v-if=\"item.count != null\" class=\"e-nav-count\">{{ item.count }}</span>\n </template>\n </LinkNav>\n</template>\n\n<style>\n@layer e.page {\n .e-nav ul {\n display: grid;\n gap: calc(var(--e-space-1) / 2);\n margin: 0;\n padding: 0;\n list-style: none;\n }\n\n .e-nav:not(.e-nav--horizontal) ul {\n gap: 0;\n }\n\n .e-nav:not(.e-nav--horizontal) li + li::before {\n content: \"\";\n display: block;\n height: var(--e-stroke-hair);\n margin-block: var(--e-space-2);\n background: color-mix(in srgb, var(--e-border) 60%, transparent);\n }\n\n .e-nav-item {\n display: flex;\n align-items: center;\n gap: var(--e-space-3);\n height: var(--e-control-height);\n box-sizing: border-box;\n padding: 0 var(--e-space-3);\n border: var(--e-stroke-edge) solid transparent;\n border-radius: var(--e-radius-md);\n color: var(--e-ink);\n font: 400 var(--e-text-md) / 1 var(--e-font-sans);\n text-decoration: none;\n transition: background-color var(--e-duration-tap) var(--e-easing-out);\n }\n\n .e-nav-item:hover {\n background: var(--e-surface-hover);\n }\n\n .e-nav-item:focus-visible {\n outline: var(--e-stroke-focus) solid var(--e-focus-ring);\n outline-offset: var(--e-focus-gap);\n }\n\n .e-nav-item[aria-current=\"page\"] {\n background: color-mix(in srgb, var(--e-surface-tint), var(--e-ink) 3%);\n font-weight: 600;\n border-color: var(--e-primary);\n border-bottom-width: calc(var(--e-stroke-edge) + var(--e-depth));\n }\n\n .e-nav-label {\n flex: 1;\n min-width: 0;\n }\n\n .e-nav--horizontal {\n display: flex;\n flex-wrap: wrap;\n align-items: center;\n gap: var(--e-space-2) var(--e-space-4);\n }\n\n /* The separator sits inside the next item's li, so the list has no gap of its own: the margins on the separator space both sides equally. */\n .e-nav--horizontal ul {\n display: flex;\n flex-wrap: wrap;\n gap: 0;\n }\n\n .e-nav--horizontal li {\n display: flex;\n align-items: center;\n }\n\n .e-nav--horizontal li + li::before {\n content: \"\";\n width: var(--e-stroke-hair);\n height: 1.75rem;\n margin-inline: var(--e-space-2);\n background: color-mix(in srgb, var(--e-border) 60%, transparent);\n }\n\n .e-nav--horizontal .e-nav-heading {\n margin: 0;\n padding-inline: 0;\n }\n\n .e-nav-count {\n min-width: var(--e-space-6);\n padding: 0 var(--e-space-2);\n border-radius: var(--e-radius-pill);\n background: color-mix(in srgb, var(--e-primary) 12%, var(--e-surface));\n box-shadow: inset 0 0 0 var(--e-stroke-hair) var(--e-primary);\n outline: var(--e-stroke-hair) solid var(--e-primary);\n outline-offset: calc(-1 * var(--e-stroke-hair));\n font: 600 var(--e-text-xs) / 20px var(--e-font-mono);\n text-align: center;\n }\n\n @media (prefers-reduced-motion: reduce) {\n .e-nav-item {\n transition: none;\n }\n }\n\n @media (forced-colors: active) {\n .e-nav-item[aria-current=\"page\"] {\n border-color: Highlight;\n }\n }\n}\n</style>\n"],"mappings":";;;;;;;;;;;;;;;;;;EAgBA,IAAMe,IAAQC,GAgBRC,IAASC,QAA6BH,EAAM,YAAY,CAAC,EAAE,OAAOA,EAAM,SAAS,CAAC,EAAE,CAAC,CAAC;E,kBAI1Ff,EAAA,GAAAC,EAcUC,GAAA;GAbR,OAAKC,EAAA,CAAC,SACEa,EAAA,gBAAW,gBAAA,mBAAA,CAAA;GAClB,QAAQC,EAAA;GACR,OAAOD,EAAA;GACP,kBAAgBA,EAAA;GACjB,cAAW;GACX,iBAAc;;GAEH,MAAIZ,GAC+B,EAD3B,cAAI;IACRmB,EAAK,QAAlBvB,EAAA,GAAAC,EAA4CI,GAAA;;KAAnB,MAAMkB,EAAK;;IACpChB,EAAiD,QAAjDK,GAAiDJ,EAApBe,EAAK,KAAK,GAAA,CAAA;IAC3BA,EAAK,SAAK,O,aAAtBvB,EAAA,GAAAS,EAA2E,QAA3EI,GAA2EL,EAApBe,EAAK,KAAK,GAAA,CAAA"}
1
+ {"version":3,"file":"ENavList.vue_vue_type_script_setup_true_lang.js","names":["_openBlock","_createBlock","LinkNav","_normalizeClass","_withCtx","EIcon","_createCommentVNode","_createElementVNode","_toDisplayString","_createElementBlock","EIcon_default","LinkNav_default","_hoisted_1","_hoisted_2","ENavList_vue_vue_type_script_setup_true_lang_default","props","__props","groups","computed","openBlock","createBlock","normalizeClass","withCtx","item","createCommentVNode","createElementVNode","toDisplayString","createElementBlock"],"sources":["../../../src/components/NavList/ENavList.vue"],"sourcesContent":["<script setup lang=\"ts\">\nimport { computed, type Component } from \"vue\";\nimport EIcon from \"../Icon/EIcon.vue\";\nimport LinkNav, { type LinkItem, type LinkSection } from \"./LinkNav.vue\";\nimport type { IconProp } from \"../../icons/types.js\";\nimport \"../../styles/base.css\";\n\nexport interface NavItem extends LinkItem {\n /** An icon before the label. */\n icon?: IconProp;\n /** A count of things waiting on the person (bills to pay, forms to sign). */\n count?: number;\n}\n\nexport type NavSection = LinkSection<NavItem>;\n\nconst props = withDefaults(\n defineProps<{\n /** The destinations, in order: `{ label, href?, to?, icon?, count?, current? }`. With no `href` or `to` a link goes to `#`. Set `current` yourself. */\n items?: NavItem[];\n /** Destinations in labelled groups, instead of `items`: `{ label?, items }`. Give a label only when there is more than one section. */\n sections?: NavSection[];\n /** `vertical` stacks the links, for a sidebar or a menu. `horizontal` lays them in a row, for a header, with a hairline between each. Items look the same as in the vertical list: a tint on hover, and a primary outline with a heavier bottom edge on the current page. */\n orientation?: \"vertical\" | \"horizontal\";\n /** The landmark's name; give each navigation on a page its own. @default \"Main\" */\n label?: string;\n /** What renders each link: `\"a\"` by default, or `RouterLink` (or any component that takes `href` or `to` and a default slot). Give items `to`; it receives `to` or `href`, the class `e-nav-item` and `aria-current`. */\n linkComponent?: string | Component;\n }>(),\n { orientation: \"vertical\", linkComponent: \"a\" },\n);\n\nconst groups = computed<NavSection[]>(() => props.sections ?? [{ items: props.items ?? [] }]);\n</script>\n\n<template>\n <LinkNav\n class=\"e-nav\"\n :class=\"orientation === 'horizontal' && 'e-nav--horizontal'\"\n :groups=\"groups\"\n :label=\"label\"\n :link-component=\"linkComponent\"\n item-class=\"e-nav-item\"\n heading-class=\"e-nav-heading\"\n >\n <template #item=\"{ item }\">\n <EIcon v-if=\"item.icon\" :name=\"item.icon\" />\n <span class=\"e-nav-label\">{{ item.label }}</span>\n <span v-if=\"item.count != null\" class=\"e-nav-count\">{{ item.count }}</span>\n </template>\n </LinkNav>\n</template>\n\n<style>\n@layer e.page {\n .e-nav ul {\n display: grid;\n gap: calc(var(--e-space-1) / 2);\n margin: 0;\n padding: 0;\n list-style: none;\n }\n\n .e-nav:not(.e-nav--horizontal) ul {\n gap: 0;\n }\n\n .e-nav:not(.e-nav--horizontal) li + li::before {\n content: \"\";\n display: block;\n height: var(--e-stroke-hair);\n margin-block: var(--e-space-2);\n background: color-mix(in srgb, var(--e-border) 60%, transparent);\n }\n\n .e-nav-item {\n display: flex;\n align-items: center;\n gap: var(--e-space-3);\n height: var(--e-control-height);\n box-sizing: border-box;\n padding: 0 var(--e-space-3) var(--e-lift);\n\n --e-lift: 0px;\n\n border: 0;\n border-radius: var(--e-radius-md);\n color: var(--e-ink);\n font: 400 var(--e-text-md) / 1 var(--e-font-sans);\n text-decoration: none;\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-nav-item:hover {\n background-color: var(--e-surface-hover);\n }\n\n .e-nav-item:focus-visible {\n outline: var(--e-stroke-focus) solid var(--e-focus-ring);\n outline-offset: var(--e-focus-gap);\n }\n\n .e-nav-item[aria-current=\"page\"] {\n background-color: color-mix(in srgb, var(--e-surface-tint), var(--e-ink) 3%);\n font-weight: 600;\n\n --e-lift: var(--e-depth);\n --e-slab: var(--e-primary);\n\n box-shadow:\n inset 0 0 0 var(--e-stroke-edge) var(--e-primary),\n inset 0 calc(-1 * (var(--e-lift) + var(--e-stroke-edge))) 0 0 var(--e-slab);\n }\n\n .e-nav-item[aria-current=\"page\"]:hover {\n --e-slab: color-mix(in srgb, var(--e-primary), var(--e-shade-slab));\n }\n\n .e-nav-label {\n flex: 1;\n min-width: 0;\n }\n\n .e-nav--horizontal {\n display: flex;\n flex-wrap: wrap;\n align-items: center;\n gap: var(--e-space-2) var(--e-space-4);\n }\n\n /* The separator sits inside the next item's li, so the list has no gap of its own: the margins on the separator space both sides equally. */\n .e-nav--horizontal ul {\n display: flex;\n flex-wrap: wrap;\n gap: 0;\n }\n\n .e-nav--horizontal li {\n display: flex;\n align-items: center;\n }\n\n .e-nav--horizontal li + li::before {\n content: \"\";\n width: var(--e-stroke-hair);\n height: 1.75rem;\n margin-inline: var(--e-space-2);\n background: color-mix(in srgb, var(--e-border) 60%, transparent);\n }\n\n .e-nav--horizontal .e-nav-heading {\n margin: 0;\n padding-inline: 0;\n }\n\n .e-nav-count {\n min-width: var(--e-space-6);\n padding: 0 var(--e-space-2);\n border-radius: var(--e-radius-pill);\n background: color-mix(in srgb, var(--e-primary) 12%, var(--e-surface));\n box-shadow: inset 0 0 0 var(--e-stroke-hair) var(--e-primary);\n font: 600 var(--e-text-xs) / 20px var(--e-font-mono);\n text-align: center;\n }\n\n @media (prefers-reduced-motion: reduce) {\n .e-nav-item {\n transition: none;\n }\n }\n\n @media (forced-colors: active) {\n .e-nav-item[aria-current=\"page\"] {\n border-color: Highlight;\n }\n }\n}\n</style>\n"],"mappings":";;;;;;;;;;;;;;;;;;EAgBA,IAAMe,IAAQC,GAgBRC,IAASC,QAA6BH,EAAM,YAAY,CAAC,EAAE,OAAOA,EAAM,SAAS,CAAC,EAAE,CAAC,CAAC;E,kBAI1Ff,EAAA,GAAAC,EAcUC,GAAA;GAbR,OAAKC,EAAA,CAAC,SACEa,EAAA,gBAAW,gBAAA,mBAAA,CAAA;GAClB,QAAQC,EAAA;GACR,OAAOD,EAAA;GACP,kBAAgBA,EAAA;GACjB,cAAW;GACX,iBAAc;;GAEH,MAAIZ,GAC+B,EAD3B,cAAI;IACRmB,EAAK,QAAlBvB,EAAA,GAAAC,EAA4CI,GAAA;;KAAnB,MAAMkB,EAAK;;IACpChB,EAAiD,QAAjDK,GAAiDJ,EAApBe,EAAK,KAAK,GAAA,CAAA;IAC3BA,EAAK,SAAK,O,aAAtBvB,EAAA,GAAAS,EAA2E,QAA3EI,GAA2EL,EAApBe,EAAK,KAAK,GAAA,CAAA"}
@@ -1 +1 @@
1
- {"version":3,"file":"ENotice.js","names":["_sfc_main","ENotice_vue_vue_type_script_setup_true_lang_default","ENotice_default"],"sources":["../../../src/components/Notice/ENotice.vue"],"sourcesContent":["<script lang=\"ts\">\nexport type NoticeTone = \"info\" | \"success\" | \"warning\" | \"danger\";\n</script>\n\n<script setup lang=\"ts\">\nimport { computed, getCurrentInstance } from \"vue\";\nimport EActions from \"../Actions/EActions.vue\";\nimport EIcon from \"../Icon/EIcon.vue\";\nimport EIconButton from \"../IconButton/EIconButton.vue\";\nimport { useMessages } from \"../../config.js\";\nimport type { IconProp } from \"../../icons/types.js\";\nimport \"../../styles/base.css\";\nimport \"./notice.css\";\n\nconst props = withDefaults(\n defineProps<{\n /** `info` is the default; `success` confirms; `warning` needs attention; `danger` is an error and is announced at once. */\n tone?: NoticeTone;\n /** What happened, in one short line. */\n title: string;\n /** Renders the title as a heading of this level (1 to 6) so the notice is findable by heading; without it the title is a paragraph. */\n headingLevel?: 1 | 2 | 3 | 4 | 5 | 6;\n /** The id of the title element, for a parent that labels itself by it. */\n titleId?: string;\n /** The ARIA role. `danger` uses `alert`, the others `status`. `false` removes it, for a parent that announces the notice. */\n role?: string | false;\n /** Replaces the icon of the tone. */\n icon?: IconProp;\n /** Forces the close button on or off. Left out, it shows when a `@close` listener is attached. */\n closable?: boolean;\n }>(),\n { tone: \"info\", role: undefined, closable: undefined },\n);\n\nconst emit = defineEmits<{\n /** The close button was pressed. The button only shows when a listener is attached. */\n close: [];\n}>();\n\ndefineSlots<{\n /** One sentence of detail under the title. */\n default?(): unknown;\n /** Buttons for the next step; `outline` and `quiet` suit best. At the end of the row when the notice is 36rem wide or more, under the text when narrower. */\n actions?(): unknown;\n}>();\n\nconst t = useMessages();\nconst instance = getCurrentInstance();\nconst TONE_ICON: Record<NoticeTone, string> = { info: \"info\", success: \"check\", warning: \"alert\", danger: \"alert\" };\nconst role = computed(() =>\n props.role === false ? undefined : props.role || (props.tone === \"danger\" ? \"alert\" : \"status\"),\n);\nconst hasClose = () => props.closable ?? !!instance?.vnode.props?.onClose;\n</script>\n\n<template>\n <div\n class=\"e-notice\"\n :class=\"[tone !== 'info' && `e-notice--${tone}`, $slots.actions && 'e-notice--actions']\"\n :role=\"role\"\n >\n <div class=\"e-notice-grid\">\n <span class=\"e-notice-icon\"><EIcon :name=\"icon ?? TONE_ICON[tone]\" /></span>\n <div class=\"e-notice-body\">\n <component :is=\"headingLevel ? `h${headingLevel}` : 'p'\" :id=\"titleId\" class=\"e-notice-title\">\n {{ title }}\n </component>\n <div v-if=\"$slots.default\" class=\"e-notice-text\"><slot /></div>\n </div>\n <EActions v-if=\"$slots.actions\" class=\"e-notice-actions\"><slot name=\"actions\" /></EActions>\n <span v-if=\"hasClose()\" class=\"e-notice-close\">\n <EIconButton icon=\"x\" :label=\"t('dismiss')\" @click=\"emit('close')\" />\n </span>\n </div>\n </div>\n</template>\n\n<style>\n@layer e.containers {\n .e-notice {\n --e-tone: var(--e-primary);\n --e-bg: var(--e-surface-tint);\n\n container-type: inline-size;\n padding: var(--e-space-3) var(--e-space-4);\n border: var(--e-stroke-edge) solid var(--e-tone);\n\n --e-bc: var(--e-tone);\n\n outline: var(--e-stroke-edge) solid var(--e-bc);\n outline-offset: calc(-1 * var(--e-stroke-edge));\n border-left-width: calc(var(--e-stroke-edge) + 2 * var(--e-depth));\n border-radius: var(--e-radius-md);\n background: var(--e-bg);\n color: var(--e-ink);\n }\n\n .e-notice--success {\n --e-tone: var(--e-secondary);\n --e-bg: var(--e-secondary-soft);\n }\n\n .e-notice--warning {\n --e-tone: var(--e-warning-strong);\n --e-bg: var(--e-warning-soft);\n }\n\n .e-notice--danger {\n --e-tone: var(--e-danger);\n --e-bg: var(--e-danger-soft);\n }\n\n .e-notice-title {\n margin: 0;\n font: 500 var(--e-text-lg) / 24px var(--e-font-sans);\n }\n\n .e-notice-text {\n margin: 0;\n font: 400 var(--e-text-sm) / 1.45 var(--e-font-sans);\n color: var(--e-ink);\n }\n\n @media (forced-colors: active) {\n .e-notice {\n border: var(--e-stroke-edge) solid CanvasText;\n }\n }\n}\n</style>\n"],"mappings":""}
1
+ {"version":3,"file":"ENotice.js","names":["_sfc_main","ENotice_vue_vue_type_script_setup_true_lang_default","ENotice_default"],"sources":["../../../src/components/Notice/ENotice.vue"],"sourcesContent":["<script lang=\"ts\">\nexport type NoticeTone = \"info\" | \"success\" | \"warning\" | \"danger\";\n</script>\n\n<script setup lang=\"ts\">\nimport { computed, getCurrentInstance } from \"vue\";\nimport EActions from \"../Actions/EActions.vue\";\nimport EIcon from \"../Icon/EIcon.vue\";\nimport EIconButton from \"../IconButton/EIconButton.vue\";\nimport { useMessages } from \"../../config.js\";\nimport type { IconProp } from \"../../icons/types.js\";\nimport \"../../styles/base.css\";\nimport \"./notice.css\";\n\nconst props = withDefaults(\n defineProps<{\n /** `info` is the default; `success` confirms; `warning` needs attention; `danger` is an error and is announced at once. */\n tone?: NoticeTone;\n /** What happened, in one short line. */\n title: string;\n /** Renders the title as a heading of this level (1 to 6) so the notice is findable by heading; without it the title is a paragraph. */\n headingLevel?: 1 | 2 | 3 | 4 | 5 | 6;\n /** The id of the title element, for a parent that labels itself by it. */\n titleId?: string;\n /** The ARIA role. `danger` uses `alert`, the others `status`. `false` removes it, for a parent that announces the notice. */\n role?: string | false;\n /** Replaces the icon of the tone. */\n icon?: IconProp;\n /** Forces the close button on or off. Left out, it shows when a `@close` listener is attached. */\n closable?: boolean;\n }>(),\n { tone: \"info\", role: undefined, closable: undefined },\n);\n\nconst emit = defineEmits<{\n /** The close button was pressed. The button only shows when a listener is attached. */\n close: [];\n}>();\n\ndefineSlots<{\n /** One sentence of detail under the title. */\n default?(): unknown;\n /** Buttons for the next step; `outline` and `quiet` suit best. At the end of the row when the notice is 36rem wide or more, under the text when narrower. */\n actions?(): unknown;\n}>();\n\nconst t = useMessages();\nconst instance = getCurrentInstance();\nconst TONE_ICON: Record<NoticeTone, string> = { info: \"info\", success: \"check\", warning: \"alert\", danger: \"alert\" };\nconst role = computed(() =>\n props.role === false ? undefined : props.role || (props.tone === \"danger\" ? \"alert\" : \"status\"),\n);\nconst hasClose = () => props.closable ?? !!instance?.vnode.props?.onClose;\n</script>\n\n<template>\n <div\n class=\"e-notice\"\n :class=\"[tone !== 'info' && `e-notice--${tone}`, $slots.actions && 'e-notice--actions']\"\n :role=\"role\"\n >\n <div class=\"e-notice-grid\">\n <span class=\"e-notice-icon\"><EIcon :name=\"icon ?? TONE_ICON[tone]\" /></span>\n <div class=\"e-notice-body\">\n <component :is=\"headingLevel ? `h${headingLevel}` : 'p'\" :id=\"titleId\" class=\"e-notice-title\">\n {{ title }}\n </component>\n <div v-if=\"$slots.default\" class=\"e-notice-text\"><slot /></div>\n </div>\n <EActions v-if=\"$slots.actions\" class=\"e-notice-actions\"><slot name=\"actions\" /></EActions>\n <span v-if=\"hasClose()\" class=\"e-notice-close\">\n <EIconButton icon=\"x\" :label=\"t('dismiss')\" @click=\"emit('close')\" />\n </span>\n </div>\n </div>\n</template>\n\n<style>\n@layer e.containers {\n .e-notice {\n --e-tone: var(--e-primary);\n --e-bg: var(--e-surface-tint);\n\n container-type: inline-size;\n padding: var(--e-space-3) var(--e-space-4);\n padding-left: calc(var(--e-space-4) + 2 * var(--e-depth));\n border: 0;\n border-radius: var(--e-radius-md);\n background-color: var(--e-bg);\n box-shadow: inset 0 0 0 var(--e-stroke-edge) var(--e-tone);\n background-image: linear-gradient(to right, var(--e-tone) calc(var(--e-stroke-edge) + 2 * var(--e-depth)), transparent calc(var(--e-stroke-edge) + 2 * var(--e-depth)));\n background-repeat: no-repeat;\n color: var(--e-ink);\n }\n\n .e-notice--success {\n --e-tone: var(--e-secondary);\n --e-bg: var(--e-secondary-soft);\n }\n\n .e-notice--warning {\n --e-tone: var(--e-warning-strong);\n --e-bg: var(--e-warning-soft);\n }\n\n .e-notice--danger {\n --e-tone: var(--e-danger);\n --e-bg: var(--e-danger-soft);\n }\n\n .e-notice-title {\n margin: 0;\n font: 500 var(--e-text-lg) / 24px var(--e-font-sans);\n }\n\n .e-notice-text {\n margin: 0;\n font: 400 var(--e-text-sm) / 1.45 var(--e-font-sans);\n color: var(--e-ink);\n }\n\n @media (forced-colors: active) {\n .e-notice {\n border: var(--e-stroke-edge) solid CanvasText;\n }\n }\n}\n</style>\n"],"mappings":""}
@@ -1 +1 @@
1
- {"version":3,"file":"ENotice.vue_vue_type_script_setup_true_lang.js","names":["$slots","_openBlock","_createElementBlock","_normalizeClass","_createElementVNode","_createVNode","EIcon","_createBlock","_resolveDynamicComponent","_withCtx","_createTextVNode","_toDisplayString","_renderSlot","_createCommentVNode","EActions","EIconButton","_unref","EActions_default","EIcon_default","EIconButton_default","_hoisted_1","_hoisted_2","_hoisted_3","_hoisted_4","_hoisted_5","_hoisted_6","ENotice_vue_vue_type_script_setup_true_lang_default","__emit","props","__props","emit","t","useMessages","instance","getCurrentInstance","TONE_ICON","role","computed","hasClose","openBlock","createElementBlock","normalizeClass","_ctx","createElementVNode","createVNode","createBlock","resolveDynamicComponent","withCtx","createTextVNode","toDisplayString","renderSlot","createCommentVNode","unref","_cache"],"sources":["../../../src/components/Notice/ENotice.vue"],"sourcesContent":["<script lang=\"ts\">\nexport type NoticeTone = \"info\" | \"success\" | \"warning\" | \"danger\";\n</script>\n\n<script setup lang=\"ts\">\nimport { computed, getCurrentInstance } from \"vue\";\nimport EActions from \"../Actions/EActions.vue\";\nimport EIcon from \"../Icon/EIcon.vue\";\nimport EIconButton from \"../IconButton/EIconButton.vue\";\nimport { useMessages } from \"../../config.js\";\nimport type { IconProp } from \"../../icons/types.js\";\nimport \"../../styles/base.css\";\nimport \"./notice.css\";\n\nconst props = withDefaults(\n defineProps<{\n /** `info` is the default; `success` confirms; `warning` needs attention; `danger` is an error and is announced at once. */\n tone?: NoticeTone;\n /** What happened, in one short line. */\n title: string;\n /** Renders the title as a heading of this level (1 to 6) so the notice is findable by heading; without it the title is a paragraph. */\n headingLevel?: 1 | 2 | 3 | 4 | 5 | 6;\n /** The id of the title element, for a parent that labels itself by it. */\n titleId?: string;\n /** The ARIA role. `danger` uses `alert`, the others `status`. `false` removes it, for a parent that announces the notice. */\n role?: string | false;\n /** Replaces the icon of the tone. */\n icon?: IconProp;\n /** Forces the close button on or off. Left out, it shows when a `@close` listener is attached. */\n closable?: boolean;\n }>(),\n { tone: \"info\", role: undefined, closable: undefined },\n);\n\nconst emit = defineEmits<{\n /** The close button was pressed. The button only shows when a listener is attached. */\n close: [];\n}>();\n\ndefineSlots<{\n /** One sentence of detail under the title. */\n default?(): unknown;\n /** Buttons for the next step; `outline` and `quiet` suit best. At the end of the row when the notice is 36rem wide or more, under the text when narrower. */\n actions?(): unknown;\n}>();\n\nconst t = useMessages();\nconst instance = getCurrentInstance();\nconst TONE_ICON: Record<NoticeTone, string> = { info: \"info\", success: \"check\", warning: \"alert\", danger: \"alert\" };\nconst role = computed(() =>\n props.role === false ? undefined : props.role || (props.tone === \"danger\" ? \"alert\" : \"status\"),\n);\nconst hasClose = () => props.closable ?? !!instance?.vnode.props?.onClose;\n</script>\n\n<template>\n <div\n class=\"e-notice\"\n :class=\"[tone !== 'info' && `e-notice--${tone}`, $slots.actions && 'e-notice--actions']\"\n :role=\"role\"\n >\n <div class=\"e-notice-grid\">\n <span class=\"e-notice-icon\"><EIcon :name=\"icon ?? TONE_ICON[tone]\" /></span>\n <div class=\"e-notice-body\">\n <component :is=\"headingLevel ? `h${headingLevel}` : 'p'\" :id=\"titleId\" class=\"e-notice-title\">\n {{ title }}\n </component>\n <div v-if=\"$slots.default\" class=\"e-notice-text\"><slot /></div>\n </div>\n <EActions v-if=\"$slots.actions\" class=\"e-notice-actions\"><slot name=\"actions\" /></EActions>\n <span v-if=\"hasClose()\" class=\"e-notice-close\">\n <EIconButton icon=\"x\" :label=\"t('dismiss')\" @click=\"emit('close')\" />\n </span>\n </div>\n </div>\n</template>\n\n<style>\n@layer e.containers {\n .e-notice {\n --e-tone: var(--e-primary);\n --e-bg: var(--e-surface-tint);\n\n container-type: inline-size;\n padding: var(--e-space-3) var(--e-space-4);\n border: var(--e-stroke-edge) solid var(--e-tone);\n\n --e-bc: var(--e-tone);\n\n outline: var(--e-stroke-edge) solid var(--e-bc);\n outline-offset: calc(-1 * var(--e-stroke-edge));\n border-left-width: calc(var(--e-stroke-edge) + 2 * var(--e-depth));\n border-radius: var(--e-radius-md);\n background: var(--e-bg);\n color: var(--e-ink);\n }\n\n .e-notice--success {\n --e-tone: var(--e-secondary);\n --e-bg: var(--e-secondary-soft);\n }\n\n .e-notice--warning {\n --e-tone: var(--e-warning-strong);\n --e-bg: var(--e-warning-soft);\n }\n\n .e-notice--danger {\n --e-tone: var(--e-danger);\n --e-bg: var(--e-danger-soft);\n }\n\n .e-notice-title {\n margin: 0;\n font: 500 var(--e-text-lg) / 24px var(--e-font-sans);\n }\n\n .e-notice-text {\n margin: 0;\n font: 400 var(--e-text-sm) / 1.45 var(--e-font-sans);\n color: var(--e-ink);\n }\n\n @media (forced-colors: active) {\n .e-notice {\n border: var(--e-stroke-edge) solid CanvasText;\n }\n }\n}\n</style>\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;EAcA,IAAM4B,IAAQC,GAoBRC,IAAOH,GAYPI,IAAIC,EAAY,GAChBC,IAAWC,EAAmB,GAC9BC,IAAwC;GAAE,MAAM;GAAQ,SAAS;GAAS,SAAS;GAAS,QAAQ;EAAQ,GAC5GC,IAAOC,QACXT,EAAM,SAAS,KAAQ,KAAA,IAAYA,EAAM,SAASA,EAAM,SAAS,WAAW,UAAU,SACxF,GACMU,UAAiBV,EAAM,YAAY,CAAC,CAACK,GAAU,MAAM,OAAO;E,kBAIhEhC,EAAA,GAAAC,EAkBM,OAAA;GAjBJ,OAAKC,EAAA,CAAC,YAAU,CACP0B,EAAA,SAAI,UAAA,aAA4BA,EAAA,QAAQ7B,EAAAA,OAAO,WAAO,mBAAA,CAAA,CAAA;GAC9D,MAAMoC,EAAA;E,IAEPhC,EAYM,OAZNiB,GAYM;GAXJjB,EAA4E,QAA5EkB,GAA4E,CAAhDjB,EAAyCC,GAAA,EAAjC,MAAMuB,EAAA,QAAQM,EAAUN,EAAA,M;GAC5DzB,EAKM,OALNmB,GAKM,EAJJtB,EAAA,GAAAM,EAEYC,EAFIqB,EAAA,eAAY,IAAOA,EAAA,iBAAY,GAAA,GAAA;IAAW,IAAIA,EAAA;IAAS,OAAM;;IAC3E,SAAApB,QAAW,CAARC,EAAAC,EAAAkB,EAAA,KAAK,GAAA,CAAA,C;;G,gBAEC7B,EAAAA,OAAO,WAAlBC,EAAA,GAAAC,EAA+D,OAA/DsB,GAA+D,CAAdZ,EAAQ8B,EAAA,QAAA,SAAA,C;GAE3C1C,EAAAA,OAAO,WAAvBC,EAAA,GAAAM,EAA2FO,GAAA;;IAA3D,OAAM;;IAAmB,SAAAL,QAAuB,CAAvBG,EAAuB8B,EAAA,QAAA,SAAA,C;;;GACpEJ,EAAQ,KAApBrC,EAAA,GAAAC,EAEO,QAFPuB,GAEO,CADLpB,EAAqEU,GAAA;IAAxD,MAAK;IAAK,OAAOC,EAAAe,CAAA,CAAC,CAAA,SAAA;IAAc,SAAK,AAAAsB,EAAA,QAAA,MAAEvB,EAAI,OAAA"}
1
+ {"version":3,"file":"ENotice.vue_vue_type_script_setup_true_lang.js","names":["$slots","_openBlock","_createElementBlock","_normalizeClass","_createElementVNode","_createVNode","EIcon","_createBlock","_resolveDynamicComponent","_withCtx","_createTextVNode","_toDisplayString","_renderSlot","_createCommentVNode","EActions","EIconButton","_unref","EActions_default","EIcon_default","EIconButton_default","_hoisted_1","_hoisted_2","_hoisted_3","_hoisted_4","_hoisted_5","_hoisted_6","ENotice_vue_vue_type_script_setup_true_lang_default","__emit","props","__props","emit","t","useMessages","instance","getCurrentInstance","TONE_ICON","role","computed","hasClose","openBlock","createElementBlock","normalizeClass","_ctx","createElementVNode","createVNode","createBlock","resolveDynamicComponent","withCtx","createTextVNode","toDisplayString","renderSlot","createCommentVNode","unref","_cache"],"sources":["../../../src/components/Notice/ENotice.vue"],"sourcesContent":["<script lang=\"ts\">\nexport type NoticeTone = \"info\" | \"success\" | \"warning\" | \"danger\";\n</script>\n\n<script setup lang=\"ts\">\nimport { computed, getCurrentInstance } from \"vue\";\nimport EActions from \"../Actions/EActions.vue\";\nimport EIcon from \"../Icon/EIcon.vue\";\nimport EIconButton from \"../IconButton/EIconButton.vue\";\nimport { useMessages } from \"../../config.js\";\nimport type { IconProp } from \"../../icons/types.js\";\nimport \"../../styles/base.css\";\nimport \"./notice.css\";\n\nconst props = withDefaults(\n defineProps<{\n /** `info` is the default; `success` confirms; `warning` needs attention; `danger` is an error and is announced at once. */\n tone?: NoticeTone;\n /** What happened, in one short line. */\n title: string;\n /** Renders the title as a heading of this level (1 to 6) so the notice is findable by heading; without it the title is a paragraph. */\n headingLevel?: 1 | 2 | 3 | 4 | 5 | 6;\n /** The id of the title element, for a parent that labels itself by it. */\n titleId?: string;\n /** The ARIA role. `danger` uses `alert`, the others `status`. `false` removes it, for a parent that announces the notice. */\n role?: string | false;\n /** Replaces the icon of the tone. */\n icon?: IconProp;\n /** Forces the close button on or off. Left out, it shows when a `@close` listener is attached. */\n closable?: boolean;\n }>(),\n { tone: \"info\", role: undefined, closable: undefined },\n);\n\nconst emit = defineEmits<{\n /** The close button was pressed. The button only shows when a listener is attached. */\n close: [];\n}>();\n\ndefineSlots<{\n /** One sentence of detail under the title. */\n default?(): unknown;\n /** Buttons for the next step; `outline` and `quiet` suit best. At the end of the row when the notice is 36rem wide or more, under the text when narrower. */\n actions?(): unknown;\n}>();\n\nconst t = useMessages();\nconst instance = getCurrentInstance();\nconst TONE_ICON: Record<NoticeTone, string> = { info: \"info\", success: \"check\", warning: \"alert\", danger: \"alert\" };\nconst role = computed(() =>\n props.role === false ? undefined : props.role || (props.tone === \"danger\" ? \"alert\" : \"status\"),\n);\nconst hasClose = () => props.closable ?? !!instance?.vnode.props?.onClose;\n</script>\n\n<template>\n <div\n class=\"e-notice\"\n :class=\"[tone !== 'info' && `e-notice--${tone}`, $slots.actions && 'e-notice--actions']\"\n :role=\"role\"\n >\n <div class=\"e-notice-grid\">\n <span class=\"e-notice-icon\"><EIcon :name=\"icon ?? TONE_ICON[tone]\" /></span>\n <div class=\"e-notice-body\">\n <component :is=\"headingLevel ? `h${headingLevel}` : 'p'\" :id=\"titleId\" class=\"e-notice-title\">\n {{ title }}\n </component>\n <div v-if=\"$slots.default\" class=\"e-notice-text\"><slot /></div>\n </div>\n <EActions v-if=\"$slots.actions\" class=\"e-notice-actions\"><slot name=\"actions\" /></EActions>\n <span v-if=\"hasClose()\" class=\"e-notice-close\">\n <EIconButton icon=\"x\" :label=\"t('dismiss')\" @click=\"emit('close')\" />\n </span>\n </div>\n </div>\n</template>\n\n<style>\n@layer e.containers {\n .e-notice {\n --e-tone: var(--e-primary);\n --e-bg: var(--e-surface-tint);\n\n container-type: inline-size;\n padding: var(--e-space-3) var(--e-space-4);\n padding-left: calc(var(--e-space-4) + 2 * var(--e-depth));\n border: 0;\n border-radius: var(--e-radius-md);\n background-color: var(--e-bg);\n box-shadow: inset 0 0 0 var(--e-stroke-edge) var(--e-tone);\n background-image: linear-gradient(to right, var(--e-tone) calc(var(--e-stroke-edge) + 2 * var(--e-depth)), transparent calc(var(--e-stroke-edge) + 2 * var(--e-depth)));\n background-repeat: no-repeat;\n color: var(--e-ink);\n }\n\n .e-notice--success {\n --e-tone: var(--e-secondary);\n --e-bg: var(--e-secondary-soft);\n }\n\n .e-notice--warning {\n --e-tone: var(--e-warning-strong);\n --e-bg: var(--e-warning-soft);\n }\n\n .e-notice--danger {\n --e-tone: var(--e-danger);\n --e-bg: var(--e-danger-soft);\n }\n\n .e-notice-title {\n margin: 0;\n font: 500 var(--e-text-lg) / 24px var(--e-font-sans);\n }\n\n .e-notice-text {\n margin: 0;\n font: 400 var(--e-text-sm) / 1.45 var(--e-font-sans);\n color: var(--e-ink);\n }\n\n @media (forced-colors: active) {\n .e-notice {\n border: var(--e-stroke-edge) solid CanvasText;\n }\n }\n}\n</style>\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;EAcA,IAAM4B,IAAQC,GAoBRC,IAAOH,GAYPI,IAAIC,EAAY,GAChBC,IAAWC,EAAmB,GAC9BC,IAAwC;GAAE,MAAM;GAAQ,SAAS;GAAS,SAAS;GAAS,QAAQ;EAAQ,GAC5GC,IAAOC,QACXT,EAAM,SAAS,KAAQ,KAAA,IAAYA,EAAM,SAASA,EAAM,SAAS,WAAW,UAAU,SACxF,GACMU,UAAiBV,EAAM,YAAY,CAAC,CAACK,GAAU,MAAM,OAAO;E,kBAIhEhC,EAAA,GAAAC,EAkBM,OAAA;GAjBJ,OAAKC,EAAA,CAAC,YAAU,CACP0B,EAAA,SAAI,UAAA,aAA4BA,EAAA,QAAQ7B,EAAAA,OAAO,WAAO,mBAAA,CAAA,CAAA;GAC9D,MAAMoC,EAAA;E,IAEPhC,EAYM,OAZNiB,GAYM;GAXJjB,EAA4E,QAA5EkB,GAA4E,CAAhDjB,EAAyCC,GAAA,EAAjC,MAAMuB,EAAA,QAAQM,EAAUN,EAAA,M;GAC5DzB,EAKM,OALNmB,GAKM,EAJJtB,EAAA,GAAAM,EAEYC,EAFIqB,EAAA,eAAY,IAAOA,EAAA,iBAAY,GAAA,GAAA;IAAW,IAAIA,EAAA;IAAS,OAAM;;IAC3E,SAAApB,QAAW,CAARC,EAAAC,EAAAkB,EAAA,KAAK,GAAA,CAAA,C;;G,gBAEC7B,EAAAA,OAAO,WAAlBC,EAAA,GAAAC,EAA+D,OAA/DsB,GAA+D,CAAdZ,EAAQ8B,EAAA,QAAA,SAAA,C;GAE3C1C,EAAAA,OAAO,WAAvBC,EAAA,GAAAM,EAA2FO,GAAA;;IAA3D,OAAM;;IAAmB,SAAAL,QAAuB,CAAvBG,EAAuB8B,EAAA,QAAA,SAAA,C;;;GACpEJ,EAAQ,KAApBrC,EAAA,GAAAC,EAEO,QAFPuB,GAEO,CADLpB,EAAqEU,GAAA;IAAxD,MAAK;IAAK,OAAOC,EAAAe,CAAA,CAAC,CAAA,SAAA;IAAc,SAAK,AAAAsB,EAAA,QAAA,MAAEvB,EAAI,OAAA"}
@@ -1 +1 @@
1
- {"version":3,"file":"EOtpField.js","names":["_sfc_main","EOtpField_vue_vue_type_script_setup_true_lang_default","EOtpField_default"],"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":""}
1
+ {"version":3,"file":"EOtpField.js","names":["_sfc_main","EOtpField_vue_vue_type_script_setup_true_lang_default","EOtpField_default"],"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":""}
@@ -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":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;EAUA,IAAMsB,IAAQC,GAgCRC,IAAOH,GAMPI,IAAQzB,EAAmBuB,GAAA,YAAgB,GAE3CI,IAAIC,EAAY,GAChBC,IAAQC,EAAc,GACtBC,IAAUC,QAAeV,EAAM,cAAc,MAAM,GACnDW,IAAoC,CAAC;EAE3C,SAASC,EAAM,GAAoB;GACjC,IAAMC,IAAO,OAAOC,KAAK,EAAE;GAC3B,QAAQL,EAAQ,QAAQI,EAAK,QAAQ,OAAO,EAAE,IAAIA,EAAK,QAAQ,eAAe,EAAE,CAAC,CAAC,YAAY,EAAA,CAAG,MAC/F,GACAb,EAAM,MACR;EACF;EACA,IAAMe,IAAQL,QAAeE,EAAMT,EAAM,KAAK,CAAC,GAE3Ca,IAAOD,EAAM;EACjB,EAAMA,IAAQ,MAAO,IAAOE,GAAI,EAAE,OAAO,OAAO,CAAC;EAEjD,SAASC,EAAO,GAAc;GAC5B,IAAON,EAAMO,CAAI;GACjB,IAAMC,IAAOJ;GAGb,AAFA,IAAOG,GACP,EAAM,QAAQA,GACVA,EAAK,WAAWnB,EAAM,UAAUoB,MAASD,KAAMjB,EAAK,YAAYiB,CAAI;EAC1E;EACA,SAASE,EAAQ,GAAW;GAC1B,EAAK,KAAK,IAAI,GAAG,KAAK,IAAIrB,EAAM,SAAS,GAAGsB,CAAC,CAAC,EAAE,EAAE,MAAM;EAC1D;EACA,IAAMC,KAAW,GAAW,MAAcN,EAAE,MAAM,GAAGK,CAAC,IAAIL,EAAE,MAAMK,IAAI,CAAC;EACvE,SAASE,EAAI,GAAW,GAAc;GACpC,IAAMC,IAAQb,EAAMC,CAAI;GACxB,IAAI,CAACY,GAAO;GACZ,IAAMC,IAAOD,EAAM,UAAUzB,EAAM,SAAS,IAAI,KAAK,IAAIsB,GAAGN,EAAK,MAAM;GAEvE,AADAE,EAAOF,EAAK,MAAM,GAAGU,CAAI,IAAID,CAAK,GAClCJ,EAAQK,IAAOD,EAAM,MAAM;EAC7B;EACA,SAASE,EAAQ,GAAW,GAAU;GACpC,IAAMC,IAASC,EAAE,QACXZ,IAAID,GACNc,IAAMF,EAAO;GACjB,IAAI,CAACE,GAAK;IACR,EAAOP,EAAQN,GAAGK,CAAC,CAAC;IACpB;GACF;GACA,IAAIL,EAAEK,MAAMQ,EAAI,WAAW,GAAG;IAC5B,IAAMC,IAAID,EAAI,QAAQb,EAAEK,EAAG;IAC3B,IAAMS,KAAK,IAAIR,EAAQO,GAAKC,CAAC,IAAID,EAAI,OAAO,CAAC;GAC/C;GACA,IAAML,IAAQb,EAAMkB,CAAG;GACvB,AAAKL,MAIDA,EAAM,WAAW,KAAKH,IAAIL,EAAE,UAC9BC,EAAOD,EAAE,MAAM,GAAGK,CAAC,IAAIG,IAAQR,EAAE,MAAMK,IAAI,CAAC,CAAC,GAC7CD,EAAQC,IAAI,CAAC,KACRE,EAAIF,GAAGG,CAAK,IACnB,EAAO,QAAQT,EAAKM,MAAM;EAC5B;EACA,SAASU,EAAM,GAAW,GAAkB;GAC1C,IAAMf,IAAID,GACJe,IAAIF,EAAE;GACZ,AAAIE,MAAM,eACRF,EAAE,eAAe,GACbZ,EAAEK,MACJJ,EAAOK,EAAQN,GAAGK,CAAC,CAAC,GACpBD,EAAQC,CAAC,KACAA,IAAI,MACbJ,EAAOK,EAAQN,GAAGK,IAAI,CAAC,CAAC,GACxBD,EAAQC,IAAI,CAAC,MAENS,MAAM,YACfF,EAAE,eAAe,GACjBX,EAAOK,EAAQN,GAAGK,CAAC,CAAC,KACXS,MAAM,eACfF,EAAE,eAAe,GACjBR,EAAQC,IAAI,CAAC,KACJS,MAAM,gBACfF,EAAE,eAAe,GACjBR,EAAQ,KAAK,IAAIC,IAAI,GAAGL,EAAE,MAAM,CAAC,KACxBc,MAAM,UACfF,EAAE,eAAe,GACjBR,EAAQ,CAAC,KACAU,MAAM,UACfF,EAAE,eAAe,GACjBR,EAAQJ,EAAE,MAAM;EAEpB;EACA,SAASgB,EAAQ,GAAW;GAC1B,AAAIX,IAAIN,EAAK,UAAQK,EAAQL,EAAK,MAAM;EAC1C;EACA,SAASkB,EAAQ,GAAW,GAAmB;GAE7C,AADAL,EAAE,eAAe,GACjBL,EAAIF,GAAGO,EAAE,eAAe,QAAQ,MAAM,KAAK,EAAE;EAC/C;E,OAEAM,QAAgB;GACd,AAAInC,EAAM,aAAWqB,EAAQL,EAAK,MAAM;EAC1C,CAAC,GAEDlB,EAAa,EACX,aAAauB,EAAQL,EAAK,MAAM,EAClC,CAAC,I,UAICrC,EAAA,GAAAC,EAuCSC,GAvCTC,EACUC,EAsCDwB,CAAA,CAtCM,CAAC,QAAO,GAAA;GACpB,IAAIN,EAAA;GACJ,OAAOA,EAAA,SAASlB,EAAAsB,CAAA,CAAC,CAAA,kBAAA;GACjB,cAAYJ,EAAA;GACZ,MAAMA,EAAA;GACN,OAAOA,EAAA;GACP,UAAUA,EAAA;GACV,UAAUA,EAAA;;GAEA,SAAOjB,GAAE,MAAK,CACvBC,EA0BM,OA1BNH,EA0BM;IA1BD,MAAK;IAAS,mBAAe,GAAK4D,EAAM,GAAE;IAAU,OAAM;GAAgB,GAAA3D,EAAAwB,CAAA,CAAK,CAAC,MAAK,CAAA,GAAA,EACxF5B,EAAA,EAAA,GAAAO,EAuBWC,GAAA,MAAAC,EAvBWa,EAAA,SAAL,OAAmBtB,EAAA,GAAAO,EAAAC,GAAA,EAAA,KAAAmC,EAAC,GAAA,CACvBrB,EAAA,aAAaqB,IAAC,MAASA,IAAC,KAAQrB,EAAA,aAAS,KAArDtB,EAAA,GAAAO,EAAoG,QAApGM,CAAoG,K,WACpGP,EAoBE,SAAA;IAnBC,IAAIqC,MAAC,IAASoB,EAAM,KAAK,KAAA;;IACzB,MAAM,MAAQ,EAAKpB,IAAC,KAAQyB;IAC7B,OAAM;IACN,MAAK;IACJ,WAAWtC,EAAA,QAAO,YAAA;IAClB,cAAca,MAAC,IAAA,kBAAA;IAChB,gBAAe;IACd,YAAY;IACZ,OAAOP,EAAA,MAAMO,IAAC,MAAA;IACd,UAAUrB,EAAA;IACV,UAAUA,EAAA;IACV,eAAac,EAAA,MAAMO,IAAC,KAAA,KAAa,KAAA;IACjC,cAAYvC,EAAAsB,CAAA,CAAC,CAACI,EAAA,QAAO,aAAA,WAAA;KAAA,GAAgCa;KAAC,OAASrB,EAAA;IAAM,CAAA;IACrE,gBAAcyC,EAAM;IACpB,oBAAkBA,EAAM;IACxB,UAAK,MAAEf,EAAQL,IAAC,GAAM0B,CAAM;IAC5B,YAAO,MAAEhB,EAAMV,IAAC,GAAM0B,CAAM;IAC5B,UAAK,MAAEf,EAAQX,IAAC,CAAA;IAChB,UAAK,MAAEY,EAAQZ,IAAC,GAAM0B,CAAM;G,gCAGpB/C,EAAA,QAAbtB,EAAA,GAAAO,EAA+D,SAAA;;IAA5C,MAAK;IAAU,MAAMe,EAAA;IAAO,OAAOc,EAAA"}
@@ -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\n --e-bc: transparent;\n\n outline: var(--e-stroke-edge) solid var(--e-bc);\n outline-offset: calc(-1 * var(--e-stroke-edge));\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 --e-bc: 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 border-color: var(--e-primary);\n\n --e-bc: var(--e-primary);\n\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\n --e-bc: transparent;\n\n outline: var(--e-stroke-edge) solid var(--e-bc);\n outline-offset: calc(-1 * var(--e-stroke-edge));\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 --e-bc: 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 border-color: var(--e-primary);\n\n --e-bc: var(--e-primary);\n\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\n --e-bc: var(--e-border-strong);\n\n outline: var(--e-stroke-edge) solid var(--e-bc);\n outline-offset: calc(-1 * var(--e-stroke-edge));\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\n --e-bc: var(--e-border-strong);\n\n outline: var(--e-stroke-edge) solid var(--e-bc);\n outline-offset: calc(-1 * var(--e-stroke-edge));\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":"EProgress.js","names":["_sfc_main","EProgress_vue_vue_type_script_setup_true_lang_default","EProgress_default"],"sources":["../../../src/components/Progress/EProgress.vue"],"sourcesContent":["<script setup lang=\"ts\">\nimport { computed } from \"vue\";\nimport { useMessages } from \"../../config.js\";\nimport \"../../styles/base.css\";\n\nconst props = withDefaults(\n defineProps<{\n /** What is progressing. Also the bar's accessible name. @default \"Loading\" */\n label?: string;\n /** How far along, from 0 to `max`; the fill is clamped. Leave it out while the length is unknown: the bar slides back and forth instead (indeterminate). */\n value?: number;\n /** The value that means finished. */\n max?: number;\n /** Text shown at the end of the row. @default percent */\n valueText?: string;\n }>(),\n { max: 100 },\n);\n\nconst t = useMessages();\nconst indeterminate = computed(() => props.value === undefined);\nconst percent = computed(() => Math.max(0, Math.min(100, ((props.value ?? 0) / (props.max || 100)) * 100)));\nconst showHead = computed(() => !!props.label || !indeterminate.value || !!props.valueText);\n</script>\n\n<template>\n <div class=\"e-progress\" :class=\"indeterminate && 'e-progress--indeterminate'\">\n <div v-if=\"showHead\" class=\"e-progress-head\">\n <span class=\"e-progress-label\">{{ label || t(\"loading\") }}</span>\n <span class=\"e-progress-value\">{{ valueText || (indeterminate ? \"\" : Math.round(percent) + \"%\") }}</span>\n </div>\n <div\n class=\"e-progress-track\"\n role=\"progressbar\"\n :aria-label=\"label || t('loading')\"\n aria-valuemin=\"0\"\n :aria-valuemax=\"indeterminate ? undefined : max || 100\"\n :aria-valuenow=\"indeterminate ? undefined : value\"\n :aria-busy=\"indeterminate ? 'true' : undefined\"\n >\n <div class=\"e-progress-fill\" :style=\"indeterminate ? undefined : { width: percent + '%' }\"></div>\n </div>\n </div>\n</template>\n\n<style>\n@layer e.primitives {\n .e-progress {\n display: grid;\n gap: var(--e-space-2);\n }\n\n .e-progress-head {\n display: flex;\n align-items: baseline;\n justify-content: space-between;\n gap: var(--e-space-3);\n }\n\n .e-progress-label {\n font: 500 var(--e-text-md) / 1.3 var(--e-font-sans);\n }\n\n .e-progress-value {\n font: 500 var(--e-text-sm) / 1.3 var(--e-font-mono);\n font-variant-numeric: tabular-nums;\n color: var(--e-muted);\n }\n\n .e-progress-track {\n position: relative;\n height: 10px;\n border-radius: var(--e-radius-pill);\n background: var(--e-surface-tint);\n box-shadow: inset 0 0 0 var(--e-stroke-card) var(--e-border-strong);\n outline: var(--e-stroke-card) solid var(--e-border-strong);\n outline-offset: calc(-1 * var(--e-stroke-card));\n overflow: hidden;\n }\n\n .e-progress-fill {\n height: 100%;\n border-radius: var(--e-radius-pill);\n background: var(--e-primary);\n box-shadow: inset 0 0 0 var(--e-stroke-card) var(--e-primary);\n outline: var(--e-stroke-card) solid var(--e-primary);\n outline-offset: calc(-1 * var(--e-stroke-card));\n transition: width var(--e-duration-move) var(--e-easing-out);\n }\n\n .e-progress--indeterminate .e-progress-fill {\n position: absolute;\n inset: 0 auto 0 0;\n width: 40%;\n transition: none;\n animation: e-progress-slide 1.5s cubic-bezier(0.4, 0, 0.2, 1) infinite;\n }\n\n @keyframes e-progress-slide {\n from {\n transform: translateX(-100%);\n }\n\n to {\n transform: translateX(250%);\n }\n }\n\n @media (prefers-reduced-motion: reduce) {\n .e-progress-fill {\n transition: none;\n }\n\n .e-progress--indeterminate .e-progress-fill {\n width: 100%;\n animation: none;\n background: repeating-linear-gradient(\n 135deg,\n var(--e-primary) 0 var(--e-space-2),\n transparent var(--e-space-2) calc(2 * var(--e-space-2))\n );\n }\n }\n\n @media (forced-colors: active) {\n .e-progress-track {\n border: var(--e-stroke-card) solid CanvasText;\n }\n\n .e-progress-fill {\n forced-color-adjust: none;\n background: Highlight;\n }\n\n .e-progress--indeterminate .e-progress-fill {\n background: Highlight;\n }\n }\n}\n</style>\n"],"mappings":""}
1
+ {"version":3,"file":"EProgress.js","names":["_sfc_main","EProgress_vue_vue_type_script_setup_true_lang_default","EProgress_default"],"sources":["../../../src/components/Progress/EProgress.vue"],"sourcesContent":["<script setup lang=\"ts\">\nimport { computed } from \"vue\";\nimport { useMessages } from \"../../config.js\";\nimport \"../../styles/base.css\";\n\nconst props = withDefaults(\n defineProps<{\n /** What is progressing. Also the bar's accessible name. @default \"Loading\" */\n label?: string;\n /** How far along, from 0 to `max`; the fill is clamped. Leave it out while the length is unknown: the bar slides back and forth instead (indeterminate). */\n value?: number;\n /** The value that means finished. */\n max?: number;\n /** Text shown at the end of the row. @default percent */\n valueText?: string;\n }>(),\n { max: 100 },\n);\n\nconst t = useMessages();\nconst indeterminate = computed(() => props.value === undefined);\nconst percent = computed(() => Math.max(0, Math.min(100, ((props.value ?? 0) / (props.max || 100)) * 100)));\nconst showHead = computed(() => !!props.label || !indeterminate.value || !!props.valueText);\n</script>\n\n<template>\n <div class=\"e-progress\" :class=\"indeterminate && 'e-progress--indeterminate'\">\n <div v-if=\"showHead\" class=\"e-progress-head\">\n <span class=\"e-progress-label\">{{ label || t(\"loading\") }}</span>\n <span class=\"e-progress-value\">{{ valueText || (indeterminate ? \"\" : Math.round(percent) + \"%\") }}</span>\n </div>\n <div\n class=\"e-progress-track\"\n role=\"progressbar\"\n :aria-label=\"label || t('loading')\"\n aria-valuemin=\"0\"\n :aria-valuemax=\"indeterminate ? undefined : max || 100\"\n :aria-valuenow=\"indeterminate ? undefined : value\"\n :aria-busy=\"indeterminate ? 'true' : undefined\"\n >\n <div class=\"e-progress-fill\" :style=\"indeterminate ? undefined : { width: percent + '%' }\"></div>\n </div>\n </div>\n</template>\n\n<style>\n@layer e.primitives {\n .e-progress {\n display: grid;\n gap: var(--e-space-2);\n }\n\n .e-progress-head {\n display: flex;\n align-items: baseline;\n justify-content: space-between;\n gap: var(--e-space-3);\n }\n\n .e-progress-label {\n font: 500 var(--e-text-md) / 1.3 var(--e-font-sans);\n }\n\n .e-progress-value {\n font: 500 var(--e-text-sm) / 1.3 var(--e-font-mono);\n font-variant-numeric: tabular-nums;\n color: var(--e-muted);\n }\n\n .e-progress-track {\n position: relative;\n height: 10px;\n border-radius: var(--e-radius-pill);\n background: var(--e-surface-tint);\n box-shadow: inset 0 0 0 var(--e-stroke-card) var(--e-border-strong);\n overflow: hidden;\n }\n\n .e-progress-fill {\n height: 100%;\n border-radius: var(--e-radius-pill);\n background: var(--e-primary);\n box-shadow: inset 0 0 0 var(--e-stroke-card) var(--e-primary);\n transition: width var(--e-duration-move) var(--e-easing-out);\n }\n\n .e-progress--indeterminate .e-progress-fill {\n position: absolute;\n inset: 0 auto 0 0;\n width: 40%;\n transition: none;\n animation: e-progress-slide 1.5s cubic-bezier(0.4, 0, 0.2, 1) infinite;\n }\n\n @keyframes e-progress-slide {\n from {\n transform: translateX(-100%);\n }\n\n to {\n transform: translateX(250%);\n }\n }\n\n @media (prefers-reduced-motion: reduce) {\n .e-progress-fill {\n transition: none;\n }\n\n .e-progress--indeterminate .e-progress-fill {\n width: 100%;\n animation: none;\n background: repeating-linear-gradient(\n 135deg,\n var(--e-primary) 0 var(--e-space-2),\n transparent var(--e-space-2) calc(2 * var(--e-space-2))\n );\n }\n }\n\n @media (forced-colors: active) {\n .e-progress-track {\n border: var(--e-stroke-card) solid CanvasText;\n }\n\n .e-progress-fill {\n forced-color-adjust: none;\n background: Highlight;\n }\n\n .e-progress--indeterminate .e-progress-fill {\n background: Highlight;\n }\n }\n}\n</style>\n"],"mappings":""}
@@ -1 +1 @@
1
- {"version":3,"file":"EProgress.vue_vue_type_script_setup_true_lang.js","names":["_openBlock","_createElementBlock","_normalizeClass","_createElementVNode","_toDisplayString","_unref","_createCommentVNode","_normalizeStyle","_hoisted_1","_hoisted_2","_hoisted_3","_hoisted_4","EProgress_vue_vue_type_script_setup_true_lang_default","props","__props","t","useMessages","indeterminate","computed","percent","showHead","openBlock","createElementBlock","normalizeClass","createElementVNode","toDisplayString","unref","createCommentVNode","normalizeStyle"],"sources":["../../../src/components/Progress/EProgress.vue"],"sourcesContent":["<script setup lang=\"ts\">\nimport { computed } from \"vue\";\nimport { useMessages } from \"../../config.js\";\nimport \"../../styles/base.css\";\n\nconst props = withDefaults(\n defineProps<{\n /** What is progressing. Also the bar's accessible name. @default \"Loading\" */\n label?: string;\n /** How far along, from 0 to `max`; the fill is clamped. Leave it out while the length is unknown: the bar slides back and forth instead (indeterminate). */\n value?: number;\n /** The value that means finished. */\n max?: number;\n /** Text shown at the end of the row. @default percent */\n valueText?: string;\n }>(),\n { max: 100 },\n);\n\nconst t = useMessages();\nconst indeterminate = computed(() => props.value === undefined);\nconst percent = computed(() => Math.max(0, Math.min(100, ((props.value ?? 0) / (props.max || 100)) * 100)));\nconst showHead = computed(() => !!props.label || !indeterminate.value || !!props.valueText);\n</script>\n\n<template>\n <div class=\"e-progress\" :class=\"indeterminate && 'e-progress--indeterminate'\">\n <div v-if=\"showHead\" class=\"e-progress-head\">\n <span class=\"e-progress-label\">{{ label || t(\"loading\") }}</span>\n <span class=\"e-progress-value\">{{ valueText || (indeterminate ? \"\" : Math.round(percent) + \"%\") }}</span>\n </div>\n <div\n class=\"e-progress-track\"\n role=\"progressbar\"\n :aria-label=\"label || t('loading')\"\n aria-valuemin=\"0\"\n :aria-valuemax=\"indeterminate ? undefined : max || 100\"\n :aria-valuenow=\"indeterminate ? undefined : value\"\n :aria-busy=\"indeterminate ? 'true' : undefined\"\n >\n <div class=\"e-progress-fill\" :style=\"indeterminate ? undefined : { width: percent + '%' }\"></div>\n </div>\n </div>\n</template>\n\n<style>\n@layer e.primitives {\n .e-progress {\n display: grid;\n gap: var(--e-space-2);\n }\n\n .e-progress-head {\n display: flex;\n align-items: baseline;\n justify-content: space-between;\n gap: var(--e-space-3);\n }\n\n .e-progress-label {\n font: 500 var(--e-text-md) / 1.3 var(--e-font-sans);\n }\n\n .e-progress-value {\n font: 500 var(--e-text-sm) / 1.3 var(--e-font-mono);\n font-variant-numeric: tabular-nums;\n color: var(--e-muted);\n }\n\n .e-progress-track {\n position: relative;\n height: 10px;\n border-radius: var(--e-radius-pill);\n background: var(--e-surface-tint);\n box-shadow: inset 0 0 0 var(--e-stroke-card) var(--e-border-strong);\n outline: var(--e-stroke-card) solid var(--e-border-strong);\n outline-offset: calc(-1 * var(--e-stroke-card));\n overflow: hidden;\n }\n\n .e-progress-fill {\n height: 100%;\n border-radius: var(--e-radius-pill);\n background: var(--e-primary);\n box-shadow: inset 0 0 0 var(--e-stroke-card) var(--e-primary);\n outline: var(--e-stroke-card) solid var(--e-primary);\n outline-offset: calc(-1 * var(--e-stroke-card));\n transition: width var(--e-duration-move) var(--e-easing-out);\n }\n\n .e-progress--indeterminate .e-progress-fill {\n position: absolute;\n inset: 0 auto 0 0;\n width: 40%;\n transition: none;\n animation: e-progress-slide 1.5s cubic-bezier(0.4, 0, 0.2, 1) infinite;\n }\n\n @keyframes e-progress-slide {\n from {\n transform: translateX(-100%);\n }\n\n to {\n transform: translateX(250%);\n }\n }\n\n @media (prefers-reduced-motion: reduce) {\n .e-progress-fill {\n transition: none;\n }\n\n .e-progress--indeterminate .e-progress-fill {\n width: 100%;\n animation: none;\n background: repeating-linear-gradient(\n 135deg,\n var(--e-primary) 0 var(--e-space-2),\n transparent var(--e-space-2) calc(2 * var(--e-space-2))\n );\n }\n }\n\n @media (forced-colors: active) {\n .e-progress-track {\n border: var(--e-stroke-card) solid CanvasText;\n }\n\n .e-progress-fill {\n forced-color-adjust: none;\n background: Highlight;\n }\n\n .e-progress--indeterminate .e-progress-fill {\n background: Highlight;\n }\n }\n}\n</style>\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;EAKA,IAAMa,IAAQC,GAcRC,IAAIC,EAAY,GAChBC,IAAgBC,QAAeL,EAAM,UAAU,KAAA,CAAS,GACxDM,IAAUD,QAAe,KAAK,IAAI,GAAG,KAAK,IAAI,MAAOL,EAAM,SAAS,MAAMA,EAAM,OAAO,OAAQ,GAAG,CAAC,CAAC,GACpGO,IAAWF,QAAe,CAAC,CAACL,EAAM,SAAS,CAACI,EAAc,SAAS,CAAC,CAACJ,EAAM,SAAS;E,kBAIxFb,EAAA,GAAAC,EAgBM,OAAA,EAhBD,OAAKC,EAAA,CAAC,cAAqBe,EAAA,SAAa,2BAAA,CAAA,E,IAChCG,EAAA,SAAXpB,EAAA,GAAAC,EAGM,OAHNO,GAGM,CAFJL,EAAiE,QAAjEM,GAAiEL,EAA/BU,EAAA,SAAST,EAAAU,CAAA,CAAC,CAAA,SAAA,CAAA,GAAA,CAAA,GAC5CZ,EAAyG,QAAzGO,GAAyGN,EAAvEU,EAAA,cAAcG,EAAA,QAAa,KAAQ,KAAK,MAAME,EAAA,KAAO,IAAA,IAAA,GAAA,CAAA,C,iBAEzFhB,EAUM,OAAA;GATJ,OAAM;GACN,MAAK;GACJ,cAAYW,EAAA,SAAST,EAAAU,CAAA,CAAC,CAAA,SAAA;GACvB,iBAAc;GACb,iBAAeE,EAAA,QAAgB,KAAA,IAAYH,EAAA,OAAG;GAC9C,iBAAeG,EAAA,QAAgB,KAAA,IAAYH,EAAA;GAC3C,aAAWG,EAAA,QAAa,SAAY,KAAA;E,IAErCd,EAAiG,OAAA;GAA5F,OAAM;GAAmB,OAAKI,EAAEU,EAAA,QAAgB,KAAA,IAAS,EAAA,OAAYE,EAAA,QAAO,IAAA,CAAA"}
1
+ {"version":3,"file":"EProgress.vue_vue_type_script_setup_true_lang.js","names":["_openBlock","_createElementBlock","_normalizeClass","_createElementVNode","_toDisplayString","_unref","_createCommentVNode","_normalizeStyle","_hoisted_1","_hoisted_2","_hoisted_3","_hoisted_4","EProgress_vue_vue_type_script_setup_true_lang_default","props","__props","t","useMessages","indeterminate","computed","percent","showHead","openBlock","createElementBlock","normalizeClass","createElementVNode","toDisplayString","unref","createCommentVNode","normalizeStyle"],"sources":["../../../src/components/Progress/EProgress.vue"],"sourcesContent":["<script setup lang=\"ts\">\nimport { computed } from \"vue\";\nimport { useMessages } from \"../../config.js\";\nimport \"../../styles/base.css\";\n\nconst props = withDefaults(\n defineProps<{\n /** What is progressing. Also the bar's accessible name. @default \"Loading\" */\n label?: string;\n /** How far along, from 0 to `max`; the fill is clamped. Leave it out while the length is unknown: the bar slides back and forth instead (indeterminate). */\n value?: number;\n /** The value that means finished. */\n max?: number;\n /** Text shown at the end of the row. @default percent */\n valueText?: string;\n }>(),\n { max: 100 },\n);\n\nconst t = useMessages();\nconst indeterminate = computed(() => props.value === undefined);\nconst percent = computed(() => Math.max(0, Math.min(100, ((props.value ?? 0) / (props.max || 100)) * 100)));\nconst showHead = computed(() => !!props.label || !indeterminate.value || !!props.valueText);\n</script>\n\n<template>\n <div class=\"e-progress\" :class=\"indeterminate && 'e-progress--indeterminate'\">\n <div v-if=\"showHead\" class=\"e-progress-head\">\n <span class=\"e-progress-label\">{{ label || t(\"loading\") }}</span>\n <span class=\"e-progress-value\">{{ valueText || (indeterminate ? \"\" : Math.round(percent) + \"%\") }}</span>\n </div>\n <div\n class=\"e-progress-track\"\n role=\"progressbar\"\n :aria-label=\"label || t('loading')\"\n aria-valuemin=\"0\"\n :aria-valuemax=\"indeterminate ? undefined : max || 100\"\n :aria-valuenow=\"indeterminate ? undefined : value\"\n :aria-busy=\"indeterminate ? 'true' : undefined\"\n >\n <div class=\"e-progress-fill\" :style=\"indeterminate ? undefined : { width: percent + '%' }\"></div>\n </div>\n </div>\n</template>\n\n<style>\n@layer e.primitives {\n .e-progress {\n display: grid;\n gap: var(--e-space-2);\n }\n\n .e-progress-head {\n display: flex;\n align-items: baseline;\n justify-content: space-between;\n gap: var(--e-space-3);\n }\n\n .e-progress-label {\n font: 500 var(--e-text-md) / 1.3 var(--e-font-sans);\n }\n\n .e-progress-value {\n font: 500 var(--e-text-sm) / 1.3 var(--e-font-mono);\n font-variant-numeric: tabular-nums;\n color: var(--e-muted);\n }\n\n .e-progress-track {\n position: relative;\n height: 10px;\n border-radius: var(--e-radius-pill);\n background: var(--e-surface-tint);\n box-shadow: inset 0 0 0 var(--e-stroke-card) var(--e-border-strong);\n overflow: hidden;\n }\n\n .e-progress-fill {\n height: 100%;\n border-radius: var(--e-radius-pill);\n background: var(--e-primary);\n box-shadow: inset 0 0 0 var(--e-stroke-card) var(--e-primary);\n transition: width var(--e-duration-move) var(--e-easing-out);\n }\n\n .e-progress--indeterminate .e-progress-fill {\n position: absolute;\n inset: 0 auto 0 0;\n width: 40%;\n transition: none;\n animation: e-progress-slide 1.5s cubic-bezier(0.4, 0, 0.2, 1) infinite;\n }\n\n @keyframes e-progress-slide {\n from {\n transform: translateX(-100%);\n }\n\n to {\n transform: translateX(250%);\n }\n }\n\n @media (prefers-reduced-motion: reduce) {\n .e-progress-fill {\n transition: none;\n }\n\n .e-progress--indeterminate .e-progress-fill {\n width: 100%;\n animation: none;\n background: repeating-linear-gradient(\n 135deg,\n var(--e-primary) 0 var(--e-space-2),\n transparent var(--e-space-2) calc(2 * var(--e-space-2))\n );\n }\n }\n\n @media (forced-colors: active) {\n .e-progress-track {\n border: var(--e-stroke-card) solid CanvasText;\n }\n\n .e-progress-fill {\n forced-color-adjust: none;\n background: Highlight;\n }\n\n .e-progress--indeterminate .e-progress-fill {\n background: Highlight;\n }\n }\n}\n</style>\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;EAKA,IAAMa,IAAQC,GAcRC,IAAIC,EAAY,GAChBC,IAAgBC,QAAeL,EAAM,UAAU,KAAA,CAAS,GACxDM,IAAUD,QAAe,KAAK,IAAI,GAAG,KAAK,IAAI,MAAOL,EAAM,SAAS,MAAMA,EAAM,OAAO,OAAQ,GAAG,CAAC,CAAC,GACpGO,IAAWF,QAAe,CAAC,CAACL,EAAM,SAAS,CAACI,EAAc,SAAS,CAAC,CAACJ,EAAM,SAAS;E,kBAIxFb,EAAA,GAAAC,EAgBM,OAAA,EAhBD,OAAKC,EAAA,CAAC,cAAqBe,EAAA,SAAa,2BAAA,CAAA,E,IAChCG,EAAA,SAAXpB,EAAA,GAAAC,EAGM,OAHNO,GAGM,CAFJL,EAAiE,QAAjEM,GAAiEL,EAA/BU,EAAA,SAAST,EAAAU,CAAA,CAAC,CAAA,SAAA,CAAA,GAAA,CAAA,GAC5CZ,EAAyG,QAAzGO,GAAyGN,EAAvEU,EAAA,cAAcG,EAAA,QAAa,KAAQ,KAAK,MAAME,EAAA,KAAO,IAAA,IAAA,GAAA,CAAA,C,iBAEzFhB,EAUM,OAAA;GATJ,OAAM;GACN,MAAK;GACJ,cAAYW,EAAA,SAAST,EAAAU,CAAA,CAAC,CAAA,SAAA;GACvB,iBAAc;GACb,iBAAeE,EAAA,QAAgB,KAAA,IAAYH,EAAA,OAAG;GAC9C,iBAAeG,EAAA,QAAgB,KAAA,IAAYH,EAAA;GAC3C,aAAWG,EAAA,QAAa,SAAY,KAAA;E,IAErCd,EAAiG,OAAA;GAA5F,OAAM;GAAmB,OAAKI,EAAEU,EAAA,QAAgB,KAAA,IAAS,EAAA,OAAYE,EAAA,QAAO,IAAA,CAAA"}
@@ -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\n --e-bc: var(--e-border-strong);\n\n outline: var(--e-stroke-edge) solid var(--e-bc);\n outline-offset: calc(-1 * var(--e-stroke-edge));\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 --e-bc: var(--e-ink);\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);\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\n --e-bc: var(--e-focus-field);\n\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\n --e-bc: var(--e-border-strong);\n\n outline: var(--e-stroke-edge) solid var(--e-bc);\n outline-offset: calc(-1 * var(--e-stroke-edge));\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 --e-bc: var(--e-ink);\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);\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\n --e-bc: var(--e-focus-field);\n\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"}