@eos-ui/vue 0.5.0 → 0.5.1

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.
@@ -1 +1 @@
1
- {"version":3,"file":"EPageHeader.js","names":["_sfc_main","EPageHeader_vue_vue_type_script_setup_true_lang_default","EPageHeader_default"],"sources":["../../../src/components/PageHeader/EPageHeader.vue"],"sourcesContent":["<script setup lang=\"ts\">\nimport EActions from \"../Actions/EActions.vue\";\nimport \"../../styles/base.css\";\n\nwithDefaults(\n defineProps<{\n /** The page's title: where the person is, in their words (\"Visit on Oct 2\"). */\n title: string;\n /** A short line under the title. */\n description?: string;\n /** The heading level of the title, 1 by default. A page has exactly one h1; change it only when the header is not the page's title. */\n headingLevel?: 1 | 2 | 3 | 4 | 5 | 6;\n }>(),\n { headingLevel: 1 },\n);\n\ndefineSlots<{\n /** An EBreadcrumb above the title. */\n breadcrumb?(): unknown;\n /** An EStamp beside the title. */\n status?(): unknown;\n /** The page's Buttons, the main one first. */\n actions?(): unknown;\n}>();\n</script>\n\n<template>\n <div class=\"e-pagehead\">\n <slot name=\"breadcrumb\" />\n <div class=\"e-pagehead-row\">\n <div class=\"e-pagehead-text\">\n <div class=\"e-pagehead-titlerow\">\n <component :is=\"`h${headingLevel}`\" class=\"e-pagehead-title\">{{ title }}</component>\n <slot name=\"status\" />\n </div>\n <p v-if=\"description\" class=\"e-pagehead-desc\">{{ description }}</p>\n </div>\n <EActions v-if=\"$slots.actions\" class=\"e-pagehead-actions\"><slot name=\"actions\" /></EActions>\n </div>\n </div>\n</template>\n\n<style>\n@layer e.page {\n .e-pagehead {\n display: grid;\n gap: var(--e-space-3);\n margin-bottom: var(--e-space-6);\n }\n\n .e-pagehead-row {\n display: flex;\n flex-wrap: wrap;\n align-items: flex-start;\n justify-content: space-between;\n gap: var(--e-space-3) var(--e-space-4);\n }\n\n .e-pagehead-text {\n flex: 1 1 18rem;\n min-width: 0;\n }\n\n .e-pagehead-title {\n margin: 0;\n font: 500 var(--e-text-4xl) / 1.1 var(--e-font-sans);\n text-wrap: balance;\n }\n\n .e-pagehead-desc {\n margin: var(--e-space-2) 0 0;\n max-width: var(--e-measure);\n font: 400 var(--e-text-lg) / 1.45 var(--e-font-sans);\n color: var(--e-muted);\n }\n\n @media (max-width: 32rem) {\n .e-pagehead-title {\n font-size: var(--e-text-2xl);\n }\n }\n\n .e-pagehead-titlerow {\n display: flex;\n flex-wrap: wrap;\n align-items: center;\n gap: var(--e-space-2) var(--e-space-4);\n }\n\n .e-pagehead-titlerow > :not(.e-pagehead-title) {\n margin-top: var(--e-space-1);\n }\n}\n</style>\n"],"mappings":""}
1
+ {"version":3,"file":"EPageHeader.js","names":["_sfc_main","EPageHeader_vue_vue_type_script_setup_true_lang_default","EPageHeader_default"],"sources":["../../../src/components/PageHeader/EPageHeader.vue"],"sourcesContent":["<script setup lang=\"ts\">\nimport EActions from \"../Actions/EActions.vue\";\nimport \"../../styles/base.css\";\n\nwithDefaults(\n defineProps<{\n /** The page's title: where the person is, in their words (\"Visit on Oct 2\"). */\n title: string;\n /** A short line under the title. */\n description?: string;\n /** The heading level of the title, 1 by default. A page has exactly one h1; change it only when the header is not the page's title. */\n headingLevel?: 1 | 2 | 3 | 4 | 5 | 6;\n }>(),\n { headingLevel: 1 },\n);\n\ndefineSlots<{\n /** An EBreadcrumb above the title. */\n breadcrumb?(): unknown;\n /** An EStamp beside the title. */\n status?(): unknown;\n /** The page's Buttons, the main one first. */\n actions?(): unknown;\n}>();\n</script>\n\n<template>\n <div class=\"e-pagehead\">\n <slot name=\"breadcrumb\" />\n <div class=\"e-pagehead-row\">\n <div class=\"e-pagehead-text\">\n <div class=\"e-pagehead-titlerow\">\n <component :is=\"`h${headingLevel}`\" class=\"e-pagehead-title\">{{ title }}</component>\n <slot name=\"status\" />\n </div>\n <p v-if=\"description\" class=\"e-pagehead-desc\">{{ description }}</p>\n </div>\n <EActions v-if=\"$slots.actions\" class=\"e-pagehead-actions\"><slot name=\"actions\" /></EActions>\n </div>\n </div>\n</template>\n\n<style>\n@layer e.page {\n .e-pagehead {\n display: grid;\n gap: var(--e-space-3);\n margin-bottom: var(--e-space-6);\n }\n\n .e-pagehead-row {\n display: flex;\n flex-wrap: wrap;\n align-items: flex-start;\n justify-content: space-between;\n gap: var(--e-space-3) var(--e-space-4);\n }\n\n .e-pagehead-text {\n flex: 1 1 18rem;\n min-width: 0;\n }\n\n .e-pagehead-title {\n margin: 0;\n font: 500 var(--e-text-4xl) / 1.1 var(--e-font-sans);\n text-wrap: balance;\n }\n\n .e-pagehead-desc {\n margin: var(--e-space-2) 0 0;\n max-width: var(--e-measure);\n font: 400 var(--e-text-lg) / 1.45 var(--e-font-sans);\n color: var(--e-muted);\n }\n\n @media (max-width: 32rem) {\n .e-pagehead-title {\n font-size: var(--e-text-2xl);\n }\n }\n\n .e-pagehead-titlerow {\n display: flex;\n flex-wrap: wrap;\n align-items: center;\n gap: var(--e-space-2) var(--e-space-4);\n }\n}\n</style>\n"],"mappings":""}
@@ -1 +1 @@
1
- {"version":3,"file":"EPageHeader.vue_vue_type_script_setup_true_lang.js","names":["$slots","_openBlock","_createElementBlock","_renderSlot","_createElementVNode","_createBlock","_resolveDynamicComponent","_withCtx","_createTextVNode","_toDisplayString","_createCommentVNode","EActions","EActions_default","_hoisted_1","_hoisted_2","_hoisted_3","_hoisted_4","_hoisted_5","EPageHeader_vue_vue_type_script_setup_true_lang_default","openBlock","createElementBlock","renderSlot","_ctx","createElementVNode","createBlock","resolveDynamicComponent","__props","withCtx","createTextVNode","toDisplayString","createCommentVNode"],"sources":["../../../src/components/PageHeader/EPageHeader.vue"],"sourcesContent":["<script setup lang=\"ts\">\nimport EActions from \"../Actions/EActions.vue\";\nimport \"../../styles/base.css\";\n\nwithDefaults(\n defineProps<{\n /** The page's title: where the person is, in their words (\"Visit on Oct 2\"). */\n title: string;\n /** A short line under the title. */\n description?: string;\n /** The heading level of the title, 1 by default. A page has exactly one h1; change it only when the header is not the page's title. */\n headingLevel?: 1 | 2 | 3 | 4 | 5 | 6;\n }>(),\n { headingLevel: 1 },\n);\n\ndefineSlots<{\n /** An EBreadcrumb above the title. */\n breadcrumb?(): unknown;\n /** An EStamp beside the title. */\n status?(): unknown;\n /** The page's Buttons, the main one first. */\n actions?(): unknown;\n}>();\n</script>\n\n<template>\n <div class=\"e-pagehead\">\n <slot name=\"breadcrumb\" />\n <div class=\"e-pagehead-row\">\n <div class=\"e-pagehead-text\">\n <div class=\"e-pagehead-titlerow\">\n <component :is=\"`h${headingLevel}`\" class=\"e-pagehead-title\">{{ title }}</component>\n <slot name=\"status\" />\n </div>\n <p v-if=\"description\" class=\"e-pagehead-desc\">{{ description }}</p>\n </div>\n <EActions v-if=\"$slots.actions\" class=\"e-pagehead-actions\"><slot name=\"actions\" /></EActions>\n </div>\n </div>\n</template>\n\n<style>\n@layer e.page {\n .e-pagehead {\n display: grid;\n gap: var(--e-space-3);\n margin-bottom: var(--e-space-6);\n }\n\n .e-pagehead-row {\n display: flex;\n flex-wrap: wrap;\n align-items: flex-start;\n justify-content: space-between;\n gap: var(--e-space-3) var(--e-space-4);\n }\n\n .e-pagehead-text {\n flex: 1 1 18rem;\n min-width: 0;\n }\n\n .e-pagehead-title {\n margin: 0;\n font: 500 var(--e-text-4xl) / 1.1 var(--e-font-sans);\n text-wrap: balance;\n }\n\n .e-pagehead-desc {\n margin: var(--e-space-2) 0 0;\n max-width: var(--e-measure);\n font: 400 var(--e-text-lg) / 1.45 var(--e-font-sans);\n color: var(--e-muted);\n }\n\n @media (max-width: 32rem) {\n .e-pagehead-title {\n font-size: var(--e-text-2xl);\n }\n }\n\n .e-pagehead-titlerow {\n display: flex;\n flex-wrap: wrap;\n align-items: center;\n gap: var(--e-space-2) var(--e-space-4);\n }\n\n .e-pagehead-titlerow > :not(.e-pagehead-title) {\n margin-top: var(--e-space-1);\n }\n}\n</style>\n"],"mappings":";;;;;;;;;;;;;;;E,kBA2BEC,EAAA,GAAAC,EAYM,OAZNW,GAYM,CAXJV,EAA0BmB,EAAA,QAAA,YAAA,GAC1BlB,EASM,OATNU,GASM,CARJV,EAMM,OANNW,GAMM,CALJX,EAGM,OAHNY,GAGM,EAFJf,EAAA,GAAAI,EAAoFC,EAAA,IAAhEoB,EAAA,cAAY,GAAA,EAAI,OAAM,mBAAkB,GAAA;GAAC,SAAAnB,QAAW,CAARC,EAAAC,EAAAiB,EAAA,KAAK,GAAA,CAAA,C;;E,KACrEvB,EAAsBmB,EAAA,QAAA,QAAA,C,IAEfI,EAAA,eAATzB,EAAA,GAAAC,EAAmE,KAAnEe,GAAmER,EAAlBiB,EAAA,WAAW,GAAA,CAAA,K,aAE9C1B,EAAAA,OAAO,WAAvBC,EAAA,GAAAI,EAA6FM,GAAA;;GAA7D,OAAM;;GAAqB,SAAAJ,QAAuB,CAAvBJ,EAAuBmB,EAAA,QAAA,SAAA,C"}
1
+ {"version":3,"file":"EPageHeader.vue_vue_type_script_setup_true_lang.js","names":["$slots","_openBlock","_createElementBlock","_renderSlot","_createElementVNode","_createBlock","_resolveDynamicComponent","_withCtx","_createTextVNode","_toDisplayString","_createCommentVNode","EActions","EActions_default","_hoisted_1","_hoisted_2","_hoisted_3","_hoisted_4","_hoisted_5","EPageHeader_vue_vue_type_script_setup_true_lang_default","openBlock","createElementBlock","renderSlot","_ctx","createElementVNode","createBlock","resolveDynamicComponent","__props","withCtx","createTextVNode","toDisplayString","createCommentVNode"],"sources":["../../../src/components/PageHeader/EPageHeader.vue"],"sourcesContent":["<script setup lang=\"ts\">\nimport EActions from \"../Actions/EActions.vue\";\nimport \"../../styles/base.css\";\n\nwithDefaults(\n defineProps<{\n /** The page's title: where the person is, in their words (\"Visit on Oct 2\"). */\n title: string;\n /** A short line under the title. */\n description?: string;\n /** The heading level of the title, 1 by default. A page has exactly one h1; change it only when the header is not the page's title. */\n headingLevel?: 1 | 2 | 3 | 4 | 5 | 6;\n }>(),\n { headingLevel: 1 },\n);\n\ndefineSlots<{\n /** An EBreadcrumb above the title. */\n breadcrumb?(): unknown;\n /** An EStamp beside the title. */\n status?(): unknown;\n /** The page's Buttons, the main one first. */\n actions?(): unknown;\n}>();\n</script>\n\n<template>\n <div class=\"e-pagehead\">\n <slot name=\"breadcrumb\" />\n <div class=\"e-pagehead-row\">\n <div class=\"e-pagehead-text\">\n <div class=\"e-pagehead-titlerow\">\n <component :is=\"`h${headingLevel}`\" class=\"e-pagehead-title\">{{ title }}</component>\n <slot name=\"status\" />\n </div>\n <p v-if=\"description\" class=\"e-pagehead-desc\">{{ description }}</p>\n </div>\n <EActions v-if=\"$slots.actions\" class=\"e-pagehead-actions\"><slot name=\"actions\" /></EActions>\n </div>\n </div>\n</template>\n\n<style>\n@layer e.page {\n .e-pagehead {\n display: grid;\n gap: var(--e-space-3);\n margin-bottom: var(--e-space-6);\n }\n\n .e-pagehead-row {\n display: flex;\n flex-wrap: wrap;\n align-items: flex-start;\n justify-content: space-between;\n gap: var(--e-space-3) var(--e-space-4);\n }\n\n .e-pagehead-text {\n flex: 1 1 18rem;\n min-width: 0;\n }\n\n .e-pagehead-title {\n margin: 0;\n font: 500 var(--e-text-4xl) / 1.1 var(--e-font-sans);\n text-wrap: balance;\n }\n\n .e-pagehead-desc {\n margin: var(--e-space-2) 0 0;\n max-width: var(--e-measure);\n font: 400 var(--e-text-lg) / 1.45 var(--e-font-sans);\n color: var(--e-muted);\n }\n\n @media (max-width: 32rem) {\n .e-pagehead-title {\n font-size: var(--e-text-2xl);\n }\n }\n\n .e-pagehead-titlerow {\n display: flex;\n flex-wrap: wrap;\n align-items: center;\n gap: var(--e-space-2) var(--e-space-4);\n }\n}\n</style>\n"],"mappings":";;;;;;;;;;;;;;;E,kBA2BEC,EAAA,GAAAC,EAYM,OAZNW,GAYM,CAXJV,EAA0BmB,EAAA,QAAA,YAAA,GAC1BlB,EASM,OATNU,GASM,CARJV,EAMM,OANNW,GAMM,CALJX,EAGM,OAHNY,GAGM,EAFJf,EAAA,GAAAI,EAAoFC,EAAA,IAAhEoB,EAAA,cAAY,GAAA,EAAI,OAAM,mBAAkB,GAAA;GAAC,SAAAnB,QAAW,CAARC,EAAAC,EAAAiB,EAAA,KAAK,GAAA,CAAA,C;;E,KACrEvB,EAAsBmB,EAAA,QAAA,QAAA,C,IAEfI,EAAA,eAATzB,EAAA,GAAAC,EAAmE,KAAnEe,GAAmER,EAAlBiB,EAAA,WAAW,GAAA,CAAA,K,aAE9C1B,EAAAA,OAAO,WAAvBC,EAAA,GAAAI,EAA6FM,GAAA;;GAA7D,OAAM;;GAAqB,SAAAJ,QAAuB,CAAvBJ,EAAuBmB,EAAA,QAAA,SAAA,C"}
@@ -1 +1 @@
1
- {"version":3,"file":"ETabs.js","names":["_sfc_main","ETabs_vue_vue_type_script_setup_true_lang_default","ETabs_default"],"sources":["../../../src/components/Tabs/ETabs.vue"],"sourcesContent":["<script lang=\"ts\">\nexport interface TabItem {\n /** Names the tab's slot, and is the value of `v-model`. */\n id: string;\n /** The tab's words. */\n label: string;\n /** A number or short word in a small badge after the label. */\n count?: number | string;\n}\n</script>\n\n<script setup lang=\"ts\">\nimport { computed, nextTick, onMounted, ref, watch } from \"vue\";\nimport { TabsContent, TabsList, TabsRoot, TabsTrigger } from \"reka-ui\";\nimport { useConfig } from \"../../config.js\";\nimport \"../../styles/base.css\";\n\nconst props = defineProps<{\n /** The tabs, in order: `{ id, label, count? }`. Two to five across, with short labels; a vertical list can be longer. `id` names the slot and is the `v-model` value. */\n items?: TabItem[];\n /** Share the width equally between the tabs instead of letting each take its own. For a narrow container where the tabs must all fit; labels truncate. @default false */\n fill?: boolean;\n /** `vertical` stacks the tabs in a column beside their panel, for a long list of sections. Use it when there are more tabs than fit across; `fill` has no effect. @default \"horizontal\" */\n orientation?: \"horizontal\" | \"vertical\";\n /** Joins the tabs to their panel so the two read as one card: the panel is outlined, the row of tabs sits on its edge like folder tabs, and the chosen tab opens into the panel with no line between. The edge stays open where there are no tabs. @default false */\n framed?: boolean;\n}>();\n\ndefineSlots<{\n [id: string]: ((props: { item: TabItem }) => unknown) | undefined;\n /** The panel of any tab that has no slot of its own. */\n panel?(props: { item: TabItem }): unknown;\n}>();\n\nconst flat = computed(() => props.items ?? []);\n\n/** The `id` of the selected tab. Keeps its own state when unbound. @default first tab */\nconst model = defineModel<string>();\n\nconst config = useConfig();\nconst current = computed(() => model.value ?? flat.value[0]?.id);\nconst dir = computed<\"ltr\" | \"rtl\">(\n () => config.dir ?? (typeof document !== \"undefined\" && document.documentElement.dir === \"rtl\" ? \"rtl\" : \"ltr\"),\n);\n\nconst list = ref<{ $el: HTMLElement } | null>(null);\n\nasync function reveal(smooth: boolean) {\n await nextTick();\n const el = list.value?.$el;\n const tab = el?.querySelector<HTMLElement>('[aria-selected=\"true\"]');\n if (props.orientation === \"vertical\" || !el || !tab || el.scrollWidth <= el.clientWidth) return;\n const calm = typeof matchMedia !== \"undefined\" && matchMedia(\"(prefers-reduced-motion: reduce)\").matches;\n const a = tab.getBoundingClientRect();\n const b = el.getBoundingClientRect();\n el.scrollBy({ left: a.left + a.width / 2 - (b.left + b.width / 2), behavior: smooth && !calm ? \"smooth\" : \"auto\" });\n}\n\nonMounted(() => reveal(false));\nwatch(current, () => reveal(true));\n</script>\n\n<template>\n <TabsRoot\n class=\"e-tabs\"\n :class=\"{ 'e-tabs--fill': fill, 'e-tabs--vertical': orientation === 'vertical', 'e-tabs--framed': framed }\"\n :orientation=\"orientation ?? 'horizontal'\"\n :model-value=\"current\"\n :dir=\"dir\"\n @update:model-value=\"model = String($event)\"\n >\n <TabsList ref=\"list\" class=\"e-tablist\">\n <TabsTrigger v-for=\"item in flat\" :key=\"item.id\" :value=\"item.id\" class=\"e-tab\">\n {{ item.label }}\n <span v-if=\"item.count != null\" class=\"e-tab-count\">{{ item.count }}</span>\n </TabsTrigger>\n </TabsList>\n <TabsContent v-for=\"item in flat\" :key=\"item.id\" :value=\"item.id\" class=\"e-tabpanel\">\n <slot :name=\"item.id\" :item=\"item\"><slot name=\"panel\" :item=\"item\" /></slot>\n </TabsContent>\n </TabsRoot>\n</template>\n\n<style>\n@layer e.containers {\n .e-tablist {\n display: flex;\n flex: none;\n gap: 0;\n /* stylelint-disable-next-line declaration-block-no-redundant-longhand-properties -- the two axes are set apart */\n overflow-x: auto;\n overflow-y: hidden;\n scrollbar-width: none;\n }\n\n .e-tablist::-webkit-scrollbar {\n display: none;\n }\n\n /* Tabs are button-like: every tab is ringed and neighbours sit flush and share an edge, so only the outer ends of the row are rounded. The selected tab is outlined in the primary colour with a thick slab along its bottom. */\n .e-tab {\n --e-bc: var(--e-border-strong);\n\n /* A selected tab rises: the slab is a band the tab paints along one edge itself, so there is no second shape behind the corners. Every tab is one control height tall either way. */\n --e-lift: 0px;\n --e-band: calc(var(--e-lift) + var(--e-stroke-edge));\n --e-slab: var(--e-primary);\n\n position: relative;\n display: inline-flex;\n align-items: center;\n gap: var(--e-space-2);\n flex: none;\n height: var(--e-control-height);\n padding: 0 var(--e-space-4) var(--e-lift);\n border: 0;\n border-radius: 0;\n background: transparent;\n box-shadow: inset 0 0 0 var(--e-stroke-edge) var(--e-bc);\n color: var(--e-muted);\n font: 500 var(--e-text-md) / 1 var(--e-font-sans);\n cursor: pointer;\n transition:\n color var(--e-duration-tap) var(--e-easing-out),\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 /* Only the outer ends of the row are rounded. */\n .e-tab:first-child {\n border-start-start-radius: var(--e-radius-md);\n border-end-start-radius: var(--e-radius-md);\n }\n\n .e-tab:last-child {\n border-start-end-radius: var(--e-radius-md);\n border-end-end-radius: var(--e-radius-md);\n }\n\n .e-tab + .e-tab {\n margin-inline-start: calc(-1 * var(--e-stroke-edge));\n }\n\n .e-tab:hover {\n --e-bc: var(--e-ink);\n\n z-index: var(--e-z-raised);\n color: var(--e-ink);\n background-color: var(--e-surface-hover);\n }\n\n .e-tab[aria-selected=\"true\"] {\n --e-bc: var(--e-primary);\n --e-lift: var(--e-depth);\n\n z-index: var(--e-z-sticky);\n background-color: color-mix(in srgb, var(--e-surface-tint), var(--e-ink) 3%);\n box-shadow:\n inset 0 0 0 var(--e-stroke-edge) var(--e-bc),\n inset 0 calc(-1 * var(--e-band)) 0 0 var(--e-slab);\n color: var(--e-ink);\n font-weight: 600;\n }\n\n /* The slab answers the pointer too: it darkens under the cursor, in step with the face. */\n .e-tab[aria-selected=\"true\"]:hover {\n --e-slab: color-mix(in srgb, var(--e-primary), var(--e-shade-slab));\n }\n\n .e-tab:focus-visible {\n z-index: var(--e-z-focus);\n outline: var(--e-stroke-focus) solid var(--e-focus-ring);\n outline-offset: var(--e-focus-gap);\n }\n\n .e-tabs--fill .e-tablist {\n overflow-x: hidden;\n }\n\n .e-tabs--fill .e-tab {\n flex: 1 1 0;\n min-width: 0;\n justify-content: center;\n padding-inline: var(--e-space-1);\n }\n\n /* Vertical: the tabs stack beside the panel, flush and sharing edges. The selected tab rises towards the panel, so its slab is a band down the inline-start side, away from the panel, instead of along the bottom, and only the top and bottom ends of the column are rounded. */\n .e-tabs--vertical {\n display: flex;\n align-items: flex-start;\n gap: var(--e-space-4);\n }\n\n .e-tabs--vertical .e-tablist {\n flex-direction: column;\n flex: none;\n overflow: visible;\n }\n\n .e-tabs--vertical .e-tab {\n --e-lift: 0px;\n\n height: var(--e-control-height);\n padding-block-end: 0;\n justify-content: flex-start;\n border-radius: 0;\n }\n\n .e-tabs--vertical .e-tab:first-child {\n border-start-start-radius: var(--e-radius-md);\n border-start-end-radius: var(--e-radius-md);\n }\n\n .e-tabs--vertical .e-tab:last-child {\n border-end-start-radius: var(--e-radius-md);\n border-end-end-radius: var(--e-radius-md);\n }\n\n .e-tabs--vertical .e-tab + .e-tab {\n margin-inline-start: 0;\n margin-block-start: calc(-1 * var(--e-stroke-edge));\n }\n\n .e-tabs--vertical .e-tab[aria-selected=\"true\"] {\n --e-lift: var(--e-depth);\n\n padding-inline-start: calc(var(--e-space-4) + var(--e-lift));\n box-shadow:\n inset 0 0 0 var(--e-stroke-edge) var(--e-bc),\n inset var(--e-band) 0 0 0 var(--e-slab);\n }\n\n .e-tabs--vertical .e-tabpanel {\n flex: 1 1 0;\n min-width: 0;\n padding-top: 0;\n }\n\n :dir(rtl) .e-tabs--vertical .e-tab[aria-selected=\"true\"] {\n box-shadow:\n inset 0 0 0 var(--e-stroke-edge) var(--e-bc),\n inset calc(-1 * var(--e-band)) 0 0 0 var(--e-slab);\n }\n\n /* Framed: tabs and panel are one outlined card. The tab row sits over the panel's edge by one stroke, so a tab's lower edge and the panel's upper edge are the same line; the chosen tab has no edge on that side and its fill covers the panel's, opening into it. Tabs sit flush with their neighbours, square where they meet; only the card's outer corner at the first tab is rounded, and the panel's own corner beside it is square. The row always leaves a corner's width of open edge past the last tab, so the panel's curve never lands against a tab's straight edge. */\n .e-tabs--framed .e-tablist {\n position: relative;\n z-index: var(--e-z-raised);\n margin-block-end: calc(-1 * var(--e-stroke-edge));\n }\n\n .e-tabs--framed .e-tab {\n --e-bc: var(--e-border-strong);\n --e-lift: 0px;\n\n border-radius: 0;\n background-color: var(--e-surface-tint);\n }\n\n .e-tabs--framed .e-tab:first-child {\n border-start-start-radius: var(--e-radius-md);\n }\n\n .e-tabs--framed.e-tabs--fill .e-tab:last-child {\n border-start-end-radius: var(--e-radius-md);\n }\n\n .e-tabs:not(.e-tabs--fill, .e-tabs--vertical).e-tabs--framed .e-tablist {\n padding-inline-end: var(--e-radius-md);\n }\n\n .e-tabs--framed .e-tab:hover {\n background-color: var(--e-surface-hover);\n }\n\n /* The chosen tab rises like a button does, with its primary slab as a band on the edge away from the panel, and its open sides outlined in the primary colour. */\n .e-tabs--framed .e-tab[aria-selected=\"true\"] {\n --e-bc: var(--e-primary);\n --e-lift: var(--e-depth);\n\n padding-block: var(--e-lift) 0;\n background-color: var(--e-surface);\n box-shadow:\n inset var(--e-stroke-edge) 0 0 0 var(--e-bc),\n inset calc(-1 * var(--e-stroke-edge)) 0 0 0 var(--e-bc),\n inset 0 var(--e-band) 0 0 var(--e-slab);\n }\n\n .e-tabs--framed .e-tabpanel {\n padding: var(--e-space-4);\n border-radius: var(--e-radius-md);\n border-start-start-radius: 0;\n background: var(--e-surface);\n box-shadow: inset 0 0 0 var(--e-stroke-edge) var(--e-border-strong);\n }\n\n .e-tabs--framed.e-tabs--fill .e-tabpanel {\n border-start-end-radius: 0;\n }\n\n .e-tabs--framed.e-tabs--vertical {\n gap: 0;\n align-items: stretch;\n }\n\n .e-tabs--framed.e-tabs--vertical .e-tablist {\n align-self: flex-start;\n margin-block-end: var(--e-radius-md);\n margin-inline-end: calc(-1 * var(--e-stroke-edge));\n }\n\n .e-tabs--framed.e-tabs--vertical .e-tab {\n border-radius: 0;\n }\n\n .e-tabs--framed.e-tabs--vertical .e-tab:first-child {\n border-start-start-radius: var(--e-radius-md);\n }\n\n .e-tabs--framed.e-tabs--vertical .e-tab[aria-selected=\"true\"] {\n margin-block: calc(-1 * var(--e-stroke-edge)) 0;\n padding-block: 0;\n padding-inline-start: calc(var(--e-space-4) + var(--e-lift));\n box-shadow:\n inset 0 var(--e-stroke-edge) 0 0 var(--e-bc),\n inset 0 calc(-1 * var(--e-stroke-edge)) 0 0 var(--e-bc),\n inset var(--e-band) 0 0 0 var(--e-slab);\n }\n\n :dir(rtl) .e-tabs--framed.e-tabs--vertical .e-tab[aria-selected=\"true\"] {\n box-shadow:\n inset 0 var(--e-stroke-edge) 0 0 var(--e-bc),\n inset 0 calc(-1 * var(--e-stroke-edge)) 0 0 var(--e-bc),\n inset calc(-1 * var(--e-band)) 0 0 0 var(--e-slab);\n }\n\n .e-tabs--framed.e-tabs--vertical .e-tab[aria-selected=\"true\"]:first-child {\n margin-block-start: 0;\n }\n\n .e-tabs--framed.e-tabs--vertical .e-tabpanel {\n padding: var(--e-space-4);\n }\n\n .e-tab-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 color: var(--e-ink);\n }\n\n .e-tabpanel {\n padding-top: var(--e-space-4);\n }\n\n @media (prefers-reduced-motion: reduce) {\n .e-tab {\n transition: none;\n }\n }\n\n @media (forced-colors: active) {\n .e-tab[aria-selected=\"true\"] {\n forced-color-adjust: none;\n background: Highlight;\n color: HighlightText;\n }\n }\n}\n</style>\n"],"mappings":""}
1
+ {"version":3,"file":"ETabs.js","names":["_sfc_main","ETabs_vue_vue_type_script_setup_true_lang_default","ETabs_default"],"sources":["../../../src/components/Tabs/ETabs.vue"],"sourcesContent":["<script lang=\"ts\">\nexport interface TabItem {\n /** Names the tab's slot, and is the value of `v-model`. */\n id: string;\n /** The tab's words. */\n label: string;\n /** A number or short word in a small badge after the label. */\n count?: number | string;\n}\n</script>\n\n<script setup lang=\"ts\">\nimport { computed, nextTick, onMounted, ref, watch } from \"vue\";\nimport { TabsContent, TabsList, TabsRoot, TabsTrigger } from \"reka-ui\";\nimport { useConfig } from \"../../config.js\";\nimport \"../../styles/base.css\";\n\nconst props = defineProps<{\n /** The tabs, in order: `{ id, label, count? }`. Two to five across, with short labels; a vertical list can be longer. `id` names the slot and is the `v-model` value. */\n items?: TabItem[];\n /** Share the width equally between the tabs instead of letting each take its own. For a narrow container where the tabs must all fit; labels truncate. @default false */\n fill?: boolean;\n /** `vertical` stacks the tabs in a column beside their panel, for a long list of sections. Use it when there are more tabs than fit across; `fill` has no effect. @default \"horizontal\" */\n orientation?: \"horizontal\" | \"vertical\";\n /** Joins the tabs to their panel so the two read as one card: the panel is outlined, the row of tabs sits on its edge like folder tabs, and the chosen tab opens into the panel with no line between. The edge stays open where there are no tabs. @default false */\n framed?: boolean;\n}>();\n\ndefineSlots<{\n [id: string]: ((props: { item: TabItem }) => unknown) | undefined;\n /** The panel of any tab that has no slot of its own. */\n panel?(props: { item: TabItem }): unknown;\n}>();\n\nconst flat = computed(() => props.items ?? []);\n\n/** The `id` of the selected tab. Keeps its own state when unbound. @default first tab */\nconst model = defineModel<string>();\n\nconst config = useConfig();\nconst current = computed(() => model.value ?? flat.value[0]?.id);\nconst dir = computed<\"ltr\" | \"rtl\">(\n () => config.dir ?? (typeof document !== \"undefined\" && document.documentElement.dir === \"rtl\" ? \"rtl\" : \"ltr\"),\n);\n\nconst list = ref<{ $el: HTMLElement } | null>(null);\n\nasync function reveal(smooth: boolean) {\n await nextTick();\n const el = list.value?.$el;\n const tab = el?.querySelector<HTMLElement>('[aria-selected=\"true\"]');\n if (props.orientation === \"vertical\" || !el || !tab || el.scrollWidth <= el.clientWidth) return;\n const calm = typeof matchMedia !== \"undefined\" && matchMedia(\"(prefers-reduced-motion: reduce)\").matches;\n const a = tab.getBoundingClientRect();\n const b = el.getBoundingClientRect();\n el.scrollBy({ left: a.left + a.width / 2 - (b.left + b.width / 2), behavior: smooth && !calm ? \"smooth\" : \"auto\" });\n}\n\nonMounted(() => reveal(false));\nwatch(current, () => reveal(true));\n</script>\n\n<template>\n <TabsRoot\n class=\"e-tabs\"\n :class=\"{ 'e-tabs--fill': fill, 'e-tabs--vertical': orientation === 'vertical', 'e-tabs--framed': framed }\"\n :orientation=\"orientation ?? 'horizontal'\"\n :model-value=\"current\"\n :dir=\"dir\"\n @update:model-value=\"model = String($event)\"\n >\n <TabsList ref=\"list\" class=\"e-tablist\">\n <TabsTrigger v-for=\"item in flat\" :key=\"item.id\" :value=\"item.id\" class=\"e-tab\">\n {{ item.label }}\n <span v-if=\"item.count != null\" class=\"e-tab-count\">{{ item.count }}</span>\n </TabsTrigger>\n </TabsList>\n <TabsContent v-for=\"item in flat\" :key=\"item.id\" :value=\"item.id\" class=\"e-tabpanel\">\n <slot :name=\"item.id\" :item=\"item\"><slot name=\"panel\" :item=\"item\" /></slot>\n </TabsContent>\n </TabsRoot>\n</template>\n\n<style>\n@layer e.containers {\n .e-tablist {\n display: flex;\n flex: none;\n gap: 0;\n /* stylelint-disable-next-line declaration-block-no-redundant-longhand-properties -- the two axes are set apart */\n overflow-x: auto;\n overflow-y: hidden;\n scrollbar-width: none;\n }\n\n .e-tablist::-webkit-scrollbar {\n display: none;\n }\n\n /* Tabs are button-like: every tab is ringed and neighbours sit flush and share an edge, so only the outer ends of the row are rounded. The selected tab is outlined in the primary colour with a thick slab along its bottom. */\n .e-tab {\n --e-bc: var(--e-border-strong);\n\n /* A selected tab rises: the slab is a band the tab paints along one edge itself, so there is no second shape behind the corners. Every tab is one control height tall either way. */\n --e-lift: 0px;\n --e-band: calc(var(--e-lift) + var(--e-stroke-edge));\n --e-slab: var(--e-primary);\n\n position: relative;\n display: inline-flex;\n align-items: center;\n gap: var(--e-space-2);\n flex: none;\n height: var(--e-control-height);\n padding: 0 var(--e-space-4) var(--e-lift);\n border: 0;\n border-radius: 0;\n background: transparent;\n box-shadow: inset 0 0 0 var(--e-stroke-edge) var(--e-bc);\n color: var(--e-muted);\n font: 500 var(--e-text-md) / 1 var(--e-font-sans);\n cursor: pointer;\n transition:\n color var(--e-duration-tap) var(--e-easing-out),\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 /* Only the outer ends of the row are rounded. */\n .e-tab:first-child {\n border-start-start-radius: var(--e-radius-md);\n border-end-start-radius: var(--e-radius-md);\n }\n\n .e-tab:last-child {\n border-start-end-radius: var(--e-radius-md);\n border-end-end-radius: var(--e-radius-md);\n }\n\n .e-tab + .e-tab {\n margin-inline-start: calc(-1 * var(--e-stroke-edge));\n }\n\n .e-tab:hover {\n --e-bc: var(--e-ink);\n\n z-index: var(--e-z-raised);\n color: var(--e-ink);\n background-color: var(--e-surface-hover);\n }\n\n .e-tab[aria-selected=\"true\"] {\n --e-bc: var(--e-primary);\n --e-lift: var(--e-depth);\n\n z-index: var(--e-z-sticky);\n background-color: color-mix(in srgb, var(--e-surface-tint), var(--e-ink) 3%);\n box-shadow:\n inset 0 0 0 var(--e-stroke-edge) var(--e-bc),\n inset 0 calc(-1 * var(--e-band)) 0 0 var(--e-slab);\n color: var(--e-ink);\n font-weight: 600;\n }\n\n /* The slab answers the pointer too: it darkens under the cursor, in step with the face. */\n .e-tab[aria-selected=\"true\"]:hover {\n --e-slab: color-mix(in srgb, var(--e-primary), var(--e-shade-slab));\n }\n\n .e-tab:focus-visible {\n z-index: var(--e-z-focus);\n outline: var(--e-stroke-focus) solid var(--e-focus-ring);\n outline-offset: var(--e-focus-gap);\n }\n\n .e-tabs--fill > .e-tablist {\n overflow-x: hidden;\n }\n\n .e-tabs--fill > .e-tablist > .e-tab {\n flex: 1 1 0;\n min-width: 0;\n justify-content: center;\n padding-inline: var(--e-space-1);\n }\n\n /* Vertical: the tabs stack beside the panel, flush and sharing edges. The selected tab rises towards the panel, so its slab is a band down the inline-start side, away from the panel, instead of along the bottom, and only the top and bottom ends of the column are rounded. */\n .e-tabs--vertical {\n display: flex;\n align-items: flex-start;\n gap: var(--e-space-4);\n }\n\n .e-tabs--vertical > .e-tablist {\n flex-direction: column;\n flex: none;\n overflow: visible;\n }\n\n .e-tabs--vertical > .e-tablist > .e-tab {\n --e-lift: 0px;\n\n height: var(--e-control-height);\n padding-block-end: 0;\n justify-content: flex-start;\n border-radius: 0;\n }\n\n .e-tabs--vertical > .e-tablist > .e-tab:first-child {\n border-start-start-radius: var(--e-radius-md);\n border-start-end-radius: var(--e-radius-md);\n }\n\n .e-tabs--vertical > .e-tablist > .e-tab:last-child {\n border-end-start-radius: var(--e-radius-md);\n border-end-end-radius: var(--e-radius-md);\n }\n\n .e-tabs--vertical > .e-tablist > .e-tab + .e-tab {\n margin-inline-start: 0;\n margin-block-start: calc(-1 * var(--e-stroke-edge));\n }\n\n .e-tabs--vertical > .e-tablist > .e-tab[aria-selected=\"true\"] {\n --e-lift: var(--e-depth);\n\n padding-inline-start: calc(var(--e-space-4) + var(--e-lift));\n box-shadow:\n inset 0 0 0 var(--e-stroke-edge) var(--e-bc),\n inset var(--e-band) 0 0 0 var(--e-slab);\n }\n\n .e-tabs--vertical > .e-tabpanel {\n flex: 1 1 0;\n min-width: 0;\n padding-top: 0;\n }\n\n :dir(rtl) .e-tabs--vertical > .e-tablist > .e-tab[aria-selected=\"true\"] {\n box-shadow:\n inset 0 0 0 var(--e-stroke-edge) var(--e-bc),\n inset calc(-1 * var(--e-band)) 0 0 0 var(--e-slab);\n }\n\n /* Framed: tabs and panel are one outlined card. The tab row sits over the panel's edge by one stroke, so a tab's lower edge and the panel's upper edge are the same line; the chosen tab has no edge on that side and its fill covers the panel's, opening into it. Tabs sit flush with their neighbours, square where they meet; only the card's outer corner at the first tab is rounded, and the panel's own corner beside it is square. The row always leaves a corner's width of open edge past the last tab, so the panel's curve never lands against a tab's straight edge. */\n .e-tabs--framed > .e-tablist {\n position: relative;\n z-index: var(--e-z-raised);\n margin-block-end: calc(-1 * var(--e-stroke-edge));\n }\n\n .e-tabs--framed > .e-tablist > .e-tab {\n --e-bc: var(--e-border-strong);\n --e-lift: 0px;\n\n border-radius: 0;\n background-color: var(--e-surface-tint);\n }\n\n .e-tabs--framed > .e-tablist > .e-tab:first-child {\n border-start-start-radius: var(--e-radius-md);\n }\n\n .e-tabs--framed.e-tabs--fill > .e-tablist > .e-tab:last-child {\n border-start-end-radius: var(--e-radius-md);\n }\n\n .e-tabs:not(.e-tabs--fill, .e-tabs--vertical).e-tabs--framed > .e-tablist {\n padding-inline-end: var(--e-radius-md);\n }\n\n .e-tabs--framed > .e-tablist > .e-tab:hover {\n background-color: var(--e-surface-hover);\n }\n\n /* The chosen tab rises like a button does, with its primary slab as a band on the edge away from the panel, and its open sides outlined in the primary colour. */\n .e-tabs--framed > .e-tablist > .e-tab[aria-selected=\"true\"] {\n --e-bc: var(--e-primary);\n --e-lift: var(--e-depth);\n\n padding-block: var(--e-lift) 0;\n background-color: var(--e-surface);\n box-shadow:\n inset var(--e-stroke-edge) 0 0 0 var(--e-bc),\n inset calc(-1 * var(--e-stroke-edge)) 0 0 0 var(--e-bc),\n inset 0 var(--e-band) 0 0 var(--e-slab);\n }\n\n .e-tabs--framed > .e-tabpanel {\n padding: var(--e-space-4);\n border-radius: var(--e-radius-md);\n border-start-start-radius: 0;\n background: var(--e-surface);\n box-shadow: inset 0 0 0 var(--e-stroke-edge) var(--e-border-strong);\n }\n\n .e-tabs--framed.e-tabs--fill > .e-tabpanel {\n border-start-end-radius: 0;\n }\n\n .e-tabs--framed.e-tabs--vertical {\n gap: 0;\n align-items: stretch;\n }\n\n .e-tabs--framed.e-tabs--vertical > .e-tablist {\n align-self: flex-start;\n margin-block-end: var(--e-radius-md);\n margin-inline-end: calc(-1 * var(--e-stroke-edge));\n }\n\n .e-tabs--framed.e-tabs--vertical > .e-tablist > .e-tab {\n border-radius: 0;\n }\n\n .e-tabs--framed.e-tabs--vertical > .e-tablist > .e-tab:first-child {\n border-start-start-radius: var(--e-radius-md);\n }\n\n .e-tabs--framed.e-tabs--vertical > .e-tablist > .e-tab[aria-selected=\"true\"] {\n margin-block: calc(-1 * var(--e-stroke-edge)) 0;\n padding-block: 0;\n padding-inline-start: calc(var(--e-space-4) + var(--e-lift));\n box-shadow:\n inset 0 var(--e-stroke-edge) 0 0 var(--e-bc),\n inset 0 calc(-1 * var(--e-stroke-edge)) 0 0 var(--e-bc),\n inset var(--e-band) 0 0 0 var(--e-slab);\n }\n\n :dir(rtl) .e-tabs--framed.e-tabs--vertical > .e-tablist > .e-tab[aria-selected=\"true\"] {\n box-shadow:\n inset 0 var(--e-stroke-edge) 0 0 var(--e-bc),\n inset 0 calc(-1 * var(--e-stroke-edge)) 0 0 var(--e-bc),\n inset calc(-1 * var(--e-band)) 0 0 0 var(--e-slab);\n }\n\n .e-tabs--framed.e-tabs--vertical > .e-tablist > .e-tab[aria-selected=\"true\"]:first-child {\n margin-block-start: 0;\n }\n\n .e-tabs--framed.e-tabs--vertical > .e-tabpanel {\n padding: var(--e-space-4);\n }\n\n .e-tab-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 color: var(--e-ink);\n }\n\n .e-tabpanel {\n padding-top: var(--e-space-4);\n }\n\n @media (prefers-reduced-motion: reduce) {\n .e-tab {\n transition: none;\n }\n }\n\n @media (forced-colors: active) {\n .e-tab[aria-selected=\"true\"] {\n forced-color-adjust: none;\n background: Highlight;\n color: HighlightText;\n }\n }\n}\n</style>\n"],"mappings":""}
@@ -1 +1 @@
1
- {"version":3,"file":"ETabs.vue_vue_type_script_setup_true_lang.js","names":["_useModel","_openBlock","_createBlock","_unref","_normalizeClass","_withCtx","_createVNode","_createElementBlock","_Fragment","_renderList","_createTextVNode","_toDisplayString","_createCommentVNode","_renderSlot","_hoisted_1","ETabs_vue_vue_type_script_setup_true_lang_default","\"modelValue\"","\"modelModifiers\"","props","__props","flat","computed","model","useModel","config","useConfig","current","dir","list","ref","reveal","nextTick","el","tab","calm","a","b","smooth","onMounted","watch","openBlock","createBlock","unref","TabsRoot","normalizeClass","_cache","$event","withCtx","createVNode","TabsList","createElementBlock","Fragment","renderList","TabsTrigger","item","createTextVNode","toDisplayString","createCommentVNode","TabsContent","renderSlot","_ctx"],"sources":["../../../src/components/Tabs/ETabs.vue"],"sourcesContent":["<script lang=\"ts\">\nexport interface TabItem {\n /** Names the tab's slot, and is the value of `v-model`. */\n id: string;\n /** The tab's words. */\n label: string;\n /** A number or short word in a small badge after the label. */\n count?: number | string;\n}\n</script>\n\n<script setup lang=\"ts\">\nimport { computed, nextTick, onMounted, ref, watch } from \"vue\";\nimport { TabsContent, TabsList, TabsRoot, TabsTrigger } from \"reka-ui\";\nimport { useConfig } from \"../../config.js\";\nimport \"../../styles/base.css\";\n\nconst props = defineProps<{\n /** The tabs, in order: `{ id, label, count? }`. Two to five across, with short labels; a vertical list can be longer. `id` names the slot and is the `v-model` value. */\n items?: TabItem[];\n /** Share the width equally between the tabs instead of letting each take its own. For a narrow container where the tabs must all fit; labels truncate. @default false */\n fill?: boolean;\n /** `vertical` stacks the tabs in a column beside their panel, for a long list of sections. Use it when there are more tabs than fit across; `fill` has no effect. @default \"horizontal\" */\n orientation?: \"horizontal\" | \"vertical\";\n /** Joins the tabs to their panel so the two read as one card: the panel is outlined, the row of tabs sits on its edge like folder tabs, and the chosen tab opens into the panel with no line between. The edge stays open where there are no tabs. @default false */\n framed?: boolean;\n}>();\n\ndefineSlots<{\n [id: string]: ((props: { item: TabItem }) => unknown) | undefined;\n /** The panel of any tab that has no slot of its own. */\n panel?(props: { item: TabItem }): unknown;\n}>();\n\nconst flat = computed(() => props.items ?? []);\n\n/** The `id` of the selected tab. Keeps its own state when unbound. @default first tab */\nconst model = defineModel<string>();\n\nconst config = useConfig();\nconst current = computed(() => model.value ?? flat.value[0]?.id);\nconst dir = computed<\"ltr\" | \"rtl\">(\n () => config.dir ?? (typeof document !== \"undefined\" && document.documentElement.dir === \"rtl\" ? \"rtl\" : \"ltr\"),\n);\n\nconst list = ref<{ $el: HTMLElement } | null>(null);\n\nasync function reveal(smooth: boolean) {\n await nextTick();\n const el = list.value?.$el;\n const tab = el?.querySelector<HTMLElement>('[aria-selected=\"true\"]');\n if (props.orientation === \"vertical\" || !el || !tab || el.scrollWidth <= el.clientWidth) return;\n const calm = typeof matchMedia !== \"undefined\" && matchMedia(\"(prefers-reduced-motion: reduce)\").matches;\n const a = tab.getBoundingClientRect();\n const b = el.getBoundingClientRect();\n el.scrollBy({ left: a.left + a.width / 2 - (b.left + b.width / 2), behavior: smooth && !calm ? \"smooth\" : \"auto\" });\n}\n\nonMounted(() => reveal(false));\nwatch(current, () => reveal(true));\n</script>\n\n<template>\n <TabsRoot\n class=\"e-tabs\"\n :class=\"{ 'e-tabs--fill': fill, 'e-tabs--vertical': orientation === 'vertical', 'e-tabs--framed': framed }\"\n :orientation=\"orientation ?? 'horizontal'\"\n :model-value=\"current\"\n :dir=\"dir\"\n @update:model-value=\"model = String($event)\"\n >\n <TabsList ref=\"list\" class=\"e-tablist\">\n <TabsTrigger v-for=\"item in flat\" :key=\"item.id\" :value=\"item.id\" class=\"e-tab\">\n {{ item.label }}\n <span v-if=\"item.count != null\" class=\"e-tab-count\">{{ item.count }}</span>\n </TabsTrigger>\n </TabsList>\n <TabsContent v-for=\"item in flat\" :key=\"item.id\" :value=\"item.id\" class=\"e-tabpanel\">\n <slot :name=\"item.id\" :item=\"item\"><slot name=\"panel\" :item=\"item\" /></slot>\n </TabsContent>\n </TabsRoot>\n</template>\n\n<style>\n@layer e.containers {\n .e-tablist {\n display: flex;\n flex: none;\n gap: 0;\n /* stylelint-disable-next-line declaration-block-no-redundant-longhand-properties -- the two axes are set apart */\n overflow-x: auto;\n overflow-y: hidden;\n scrollbar-width: none;\n }\n\n .e-tablist::-webkit-scrollbar {\n display: none;\n }\n\n /* Tabs are button-like: every tab is ringed and neighbours sit flush and share an edge, so only the outer ends of the row are rounded. The selected tab is outlined in the primary colour with a thick slab along its bottom. */\n .e-tab {\n --e-bc: var(--e-border-strong);\n\n /* A selected tab rises: the slab is a band the tab paints along one edge itself, so there is no second shape behind the corners. Every tab is one control height tall either way. */\n --e-lift: 0px;\n --e-band: calc(var(--e-lift) + var(--e-stroke-edge));\n --e-slab: var(--e-primary);\n\n position: relative;\n display: inline-flex;\n align-items: center;\n gap: var(--e-space-2);\n flex: none;\n height: var(--e-control-height);\n padding: 0 var(--e-space-4) var(--e-lift);\n border: 0;\n border-radius: 0;\n background: transparent;\n box-shadow: inset 0 0 0 var(--e-stroke-edge) var(--e-bc);\n color: var(--e-muted);\n font: 500 var(--e-text-md) / 1 var(--e-font-sans);\n cursor: pointer;\n transition:\n color var(--e-duration-tap) var(--e-easing-out),\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 /* Only the outer ends of the row are rounded. */\n .e-tab:first-child {\n border-start-start-radius: var(--e-radius-md);\n border-end-start-radius: var(--e-radius-md);\n }\n\n .e-tab:last-child {\n border-start-end-radius: var(--e-radius-md);\n border-end-end-radius: var(--e-radius-md);\n }\n\n .e-tab + .e-tab {\n margin-inline-start: calc(-1 * var(--e-stroke-edge));\n }\n\n .e-tab:hover {\n --e-bc: var(--e-ink);\n\n z-index: var(--e-z-raised);\n color: var(--e-ink);\n background-color: var(--e-surface-hover);\n }\n\n .e-tab[aria-selected=\"true\"] {\n --e-bc: var(--e-primary);\n --e-lift: var(--e-depth);\n\n z-index: var(--e-z-sticky);\n background-color: color-mix(in srgb, var(--e-surface-tint), var(--e-ink) 3%);\n box-shadow:\n inset 0 0 0 var(--e-stroke-edge) var(--e-bc),\n inset 0 calc(-1 * var(--e-band)) 0 0 var(--e-slab);\n color: var(--e-ink);\n font-weight: 600;\n }\n\n /* The slab answers the pointer too: it darkens under the cursor, in step with the face. */\n .e-tab[aria-selected=\"true\"]:hover {\n --e-slab: color-mix(in srgb, var(--e-primary), var(--e-shade-slab));\n }\n\n .e-tab:focus-visible {\n z-index: var(--e-z-focus);\n outline: var(--e-stroke-focus) solid var(--e-focus-ring);\n outline-offset: var(--e-focus-gap);\n }\n\n .e-tabs--fill .e-tablist {\n overflow-x: hidden;\n }\n\n .e-tabs--fill .e-tab {\n flex: 1 1 0;\n min-width: 0;\n justify-content: center;\n padding-inline: var(--e-space-1);\n }\n\n /* Vertical: the tabs stack beside the panel, flush and sharing edges. The selected tab rises towards the panel, so its slab is a band down the inline-start side, away from the panel, instead of along the bottom, and only the top and bottom ends of the column are rounded. */\n .e-tabs--vertical {\n display: flex;\n align-items: flex-start;\n gap: var(--e-space-4);\n }\n\n .e-tabs--vertical .e-tablist {\n flex-direction: column;\n flex: none;\n overflow: visible;\n }\n\n .e-tabs--vertical .e-tab {\n --e-lift: 0px;\n\n height: var(--e-control-height);\n padding-block-end: 0;\n justify-content: flex-start;\n border-radius: 0;\n }\n\n .e-tabs--vertical .e-tab:first-child {\n border-start-start-radius: var(--e-radius-md);\n border-start-end-radius: var(--e-radius-md);\n }\n\n .e-tabs--vertical .e-tab:last-child {\n border-end-start-radius: var(--e-radius-md);\n border-end-end-radius: var(--e-radius-md);\n }\n\n .e-tabs--vertical .e-tab + .e-tab {\n margin-inline-start: 0;\n margin-block-start: calc(-1 * var(--e-stroke-edge));\n }\n\n .e-tabs--vertical .e-tab[aria-selected=\"true\"] {\n --e-lift: var(--e-depth);\n\n padding-inline-start: calc(var(--e-space-4) + var(--e-lift));\n box-shadow:\n inset 0 0 0 var(--e-stroke-edge) var(--e-bc),\n inset var(--e-band) 0 0 0 var(--e-slab);\n }\n\n .e-tabs--vertical .e-tabpanel {\n flex: 1 1 0;\n min-width: 0;\n padding-top: 0;\n }\n\n :dir(rtl) .e-tabs--vertical .e-tab[aria-selected=\"true\"] {\n box-shadow:\n inset 0 0 0 var(--e-stroke-edge) var(--e-bc),\n inset calc(-1 * var(--e-band)) 0 0 0 var(--e-slab);\n }\n\n /* Framed: tabs and panel are one outlined card. The tab row sits over the panel's edge by one stroke, so a tab's lower edge and the panel's upper edge are the same line; the chosen tab has no edge on that side and its fill covers the panel's, opening into it. Tabs sit flush with their neighbours, square where they meet; only the card's outer corner at the first tab is rounded, and the panel's own corner beside it is square. The row always leaves a corner's width of open edge past the last tab, so the panel's curve never lands against a tab's straight edge. */\n .e-tabs--framed .e-tablist {\n position: relative;\n z-index: var(--e-z-raised);\n margin-block-end: calc(-1 * var(--e-stroke-edge));\n }\n\n .e-tabs--framed .e-tab {\n --e-bc: var(--e-border-strong);\n --e-lift: 0px;\n\n border-radius: 0;\n background-color: var(--e-surface-tint);\n }\n\n .e-tabs--framed .e-tab:first-child {\n border-start-start-radius: var(--e-radius-md);\n }\n\n .e-tabs--framed.e-tabs--fill .e-tab:last-child {\n border-start-end-radius: var(--e-radius-md);\n }\n\n .e-tabs:not(.e-tabs--fill, .e-tabs--vertical).e-tabs--framed .e-tablist {\n padding-inline-end: var(--e-radius-md);\n }\n\n .e-tabs--framed .e-tab:hover {\n background-color: var(--e-surface-hover);\n }\n\n /* The chosen tab rises like a button does, with its primary slab as a band on the edge away from the panel, and its open sides outlined in the primary colour. */\n .e-tabs--framed .e-tab[aria-selected=\"true\"] {\n --e-bc: var(--e-primary);\n --e-lift: var(--e-depth);\n\n padding-block: var(--e-lift) 0;\n background-color: var(--e-surface);\n box-shadow:\n inset var(--e-stroke-edge) 0 0 0 var(--e-bc),\n inset calc(-1 * var(--e-stroke-edge)) 0 0 0 var(--e-bc),\n inset 0 var(--e-band) 0 0 var(--e-slab);\n }\n\n .e-tabs--framed .e-tabpanel {\n padding: var(--e-space-4);\n border-radius: var(--e-radius-md);\n border-start-start-radius: 0;\n background: var(--e-surface);\n box-shadow: inset 0 0 0 var(--e-stroke-edge) var(--e-border-strong);\n }\n\n .e-tabs--framed.e-tabs--fill .e-tabpanel {\n border-start-end-radius: 0;\n }\n\n .e-tabs--framed.e-tabs--vertical {\n gap: 0;\n align-items: stretch;\n }\n\n .e-tabs--framed.e-tabs--vertical .e-tablist {\n align-self: flex-start;\n margin-block-end: var(--e-radius-md);\n margin-inline-end: calc(-1 * var(--e-stroke-edge));\n }\n\n .e-tabs--framed.e-tabs--vertical .e-tab {\n border-radius: 0;\n }\n\n .e-tabs--framed.e-tabs--vertical .e-tab:first-child {\n border-start-start-radius: var(--e-radius-md);\n }\n\n .e-tabs--framed.e-tabs--vertical .e-tab[aria-selected=\"true\"] {\n margin-block: calc(-1 * var(--e-stroke-edge)) 0;\n padding-block: 0;\n padding-inline-start: calc(var(--e-space-4) + var(--e-lift));\n box-shadow:\n inset 0 var(--e-stroke-edge) 0 0 var(--e-bc),\n inset 0 calc(-1 * var(--e-stroke-edge)) 0 0 var(--e-bc),\n inset var(--e-band) 0 0 0 var(--e-slab);\n }\n\n :dir(rtl) .e-tabs--framed.e-tabs--vertical .e-tab[aria-selected=\"true\"] {\n box-shadow:\n inset 0 var(--e-stroke-edge) 0 0 var(--e-bc),\n inset 0 calc(-1 * var(--e-stroke-edge)) 0 0 var(--e-bc),\n inset calc(-1 * var(--e-band)) 0 0 0 var(--e-slab);\n }\n\n .e-tabs--framed.e-tabs--vertical .e-tab[aria-selected=\"true\"]:first-child {\n margin-block-start: 0;\n }\n\n .e-tabs--framed.e-tabs--vertical .e-tabpanel {\n padding: var(--e-space-4);\n }\n\n .e-tab-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 color: var(--e-ink);\n }\n\n .e-tabpanel {\n padding-top: var(--e-space-4);\n }\n\n @media (prefers-reduced-motion: reduce) {\n .e-tab {\n transition: none;\n }\n }\n\n @media (forced-colors: active) {\n .e-tab[aria-selected=\"true\"] {\n forced-color-adjust: none;\n background: Highlight;\n color: HighlightText;\n }\n }\n}\n</style>\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;EAiBA,IAAMkB,IAAQC,GAiBRC,IAAOC,QAAeH,EAAM,SAAS,CAAC,CAAC,GAGvCI,IAAQtB,EAAmBmB,GAAA,YAAC,GAE5BK,IAASC,EAAU,GACnBC,IAAUL,QAAeC,EAAM,SAASF,EAAK,MAAM,EAAE,EAAE,EAAE,GACzDO,IAAMN,QACJG,EAAO,QAAQ,OAAO,WAAa,OAAe,SAAS,gBAAgB,QAAQ,QAAQ,QAAQ,MAC3G,GAEMI,IAAOC,EAAiC,IAAI;EAElD,eAAeC,EAAO,GAAiB;GACrC,MAAMC,EAAS;GACf,IAAMC,IAAKJ,EAAK,OAAO,KACjBK,IAAMD,GAAI,cAA2B,0BAAwB;GACnE,IAAId,EAAM,gBAAgB,cAAc,CAACc,KAAM,CAACC,KAAOD,EAAG,eAAeA,EAAG,aAAa;GACzF,IAAME,IAAO,OAAO,aAAe,OAAe,WAAW,kCAAkC,CAAC,CAAC,SAC3FC,IAAIF,EAAI,sBAAsB,GAC9BG,IAAIJ,EAAG,sBAAsB;GACnC,EAAG,SAAS;IAAE,MAAMG,EAAE,OAAOA,EAAE,QAAQ,KAAKC,EAAE,OAAOA,EAAE,QAAQ;IAAI,UAAUC,KAAU,CAACH,IAAO,WAAW;GAAO,CAAC;EACpH;E,OAEAI,QAAgBR,EAAO,EAAK,CAAC,GAC7BS,EAAMb,SAAeI,EAAO,EAAI,CAAC,I,UAI/B7B,EAAA,GAAAC,EAiBWC,EAAAwC,CAAA,GAAA;GAhBT,OAAKvC,EAAA,CAAC,UAAQ;IAAA,gBACYe,EAAA;IAAI,oBAAsBA,EAAA,gBAAW;IAAA,kBAAmCA,EAAA;GAAM,CAAA,CAAA;GACvG,aAAaA,EAAA,eAAW;GACxB,eAAaO,EAAA;GACb,KAAKC,EAAA;GACL,uBAAkB,AAAAkB,EAAA,QAAA,MAAE,EAAA,QAAQ,OAAOC,CAAM;;GAE1C,SAAAzC,QAKW,CALXC,EAKWH,EAAA8C,CAAA,GAAA;IALG,SAAA;IAAJ,KAAIrB;IAAO,OAAM;;IACZ,SAAAvB,QAAoB,EAAjCJ,EAAA,EAAA,GAAAM,EAGcC,GAAA,MAAAC,EAHcW,EAAA,QAAR,OAApBnB,EAAA,GAAAC,EAGcC,EAAAkD,CAAA,GAAA;KAHqB,KAAKC,EAAK;KAAK,OAAOA,EAAK;KAAI,OAAM;;KACtE,SAAAjD,QAAgB,CAAbK,EAAAC,EAAA2C,EAAK,KAAK,IAAG,KAChB,CAAA,GAAYA,EAAK,SAAK,O,aAAtBrD,EAAA,GAAAM,EAA2E,QAA3EO,GAA2EH,EAApB2C,EAAK,KAAK,GAAA,CAAA,E;;;;G,UAGrErD,EAAA,EAAA,GAAAM,EAEcC,GAAA,MAAAC,EAFcW,EAAA,QAAR,OAApBnB,EAAA,GAAAC,EAEcC,EAAAuD,CAAA,GAAA;IAFqB,KAAKJ,EAAK;IAAK,OAAOA,EAAK;IAAI,OAAM;;IACtE,SAAAjD,QAA4E,CAA5EQ,EAA4E+C,EAAA,QAA/DN,EAAK,IAAE,EAAS,QAAI,SAA2C,CAAzCzC,EAAkC+C,EAAA,QAAA,SAAA,EAAR,QAAI,CAAA,C"}
1
+ {"version":3,"file":"ETabs.vue_vue_type_script_setup_true_lang.js","names":["_useModel","_openBlock","_createBlock","_unref","_normalizeClass","_withCtx","_createVNode","_createElementBlock","_Fragment","_renderList","_createTextVNode","_toDisplayString","_createCommentVNode","_renderSlot","_hoisted_1","ETabs_vue_vue_type_script_setup_true_lang_default","\"modelValue\"","\"modelModifiers\"","props","__props","flat","computed","model","useModel","config","useConfig","current","dir","list","ref","reveal","nextTick","el","tab","calm","a","b","smooth","onMounted","watch","openBlock","createBlock","unref","TabsRoot","normalizeClass","_cache","$event","withCtx","createVNode","TabsList","createElementBlock","Fragment","renderList","TabsTrigger","item","createTextVNode","toDisplayString","createCommentVNode","TabsContent","renderSlot","_ctx"],"sources":["../../../src/components/Tabs/ETabs.vue"],"sourcesContent":["<script lang=\"ts\">\nexport interface TabItem {\n /** Names the tab's slot, and is the value of `v-model`. */\n id: string;\n /** The tab's words. */\n label: string;\n /** A number or short word in a small badge after the label. */\n count?: number | string;\n}\n</script>\n\n<script setup lang=\"ts\">\nimport { computed, nextTick, onMounted, ref, watch } from \"vue\";\nimport { TabsContent, TabsList, TabsRoot, TabsTrigger } from \"reka-ui\";\nimport { useConfig } from \"../../config.js\";\nimport \"../../styles/base.css\";\n\nconst props = defineProps<{\n /** The tabs, in order: `{ id, label, count? }`. Two to five across, with short labels; a vertical list can be longer. `id` names the slot and is the `v-model` value. */\n items?: TabItem[];\n /** Share the width equally between the tabs instead of letting each take its own. For a narrow container where the tabs must all fit; labels truncate. @default false */\n fill?: boolean;\n /** `vertical` stacks the tabs in a column beside their panel, for a long list of sections. Use it when there are more tabs than fit across; `fill` has no effect. @default \"horizontal\" */\n orientation?: \"horizontal\" | \"vertical\";\n /** Joins the tabs to their panel so the two read as one card: the panel is outlined, the row of tabs sits on its edge like folder tabs, and the chosen tab opens into the panel with no line between. The edge stays open where there are no tabs. @default false */\n framed?: boolean;\n}>();\n\ndefineSlots<{\n [id: string]: ((props: { item: TabItem }) => unknown) | undefined;\n /** The panel of any tab that has no slot of its own. */\n panel?(props: { item: TabItem }): unknown;\n}>();\n\nconst flat = computed(() => props.items ?? []);\n\n/** The `id` of the selected tab. Keeps its own state when unbound. @default first tab */\nconst model = defineModel<string>();\n\nconst config = useConfig();\nconst current = computed(() => model.value ?? flat.value[0]?.id);\nconst dir = computed<\"ltr\" | \"rtl\">(\n () => config.dir ?? (typeof document !== \"undefined\" && document.documentElement.dir === \"rtl\" ? \"rtl\" : \"ltr\"),\n);\n\nconst list = ref<{ $el: HTMLElement } | null>(null);\n\nasync function reveal(smooth: boolean) {\n await nextTick();\n const el = list.value?.$el;\n const tab = el?.querySelector<HTMLElement>('[aria-selected=\"true\"]');\n if (props.orientation === \"vertical\" || !el || !tab || el.scrollWidth <= el.clientWidth) return;\n const calm = typeof matchMedia !== \"undefined\" && matchMedia(\"(prefers-reduced-motion: reduce)\").matches;\n const a = tab.getBoundingClientRect();\n const b = el.getBoundingClientRect();\n el.scrollBy({ left: a.left + a.width / 2 - (b.left + b.width / 2), behavior: smooth && !calm ? \"smooth\" : \"auto\" });\n}\n\nonMounted(() => reveal(false));\nwatch(current, () => reveal(true));\n</script>\n\n<template>\n <TabsRoot\n class=\"e-tabs\"\n :class=\"{ 'e-tabs--fill': fill, 'e-tabs--vertical': orientation === 'vertical', 'e-tabs--framed': framed }\"\n :orientation=\"orientation ?? 'horizontal'\"\n :model-value=\"current\"\n :dir=\"dir\"\n @update:model-value=\"model = String($event)\"\n >\n <TabsList ref=\"list\" class=\"e-tablist\">\n <TabsTrigger v-for=\"item in flat\" :key=\"item.id\" :value=\"item.id\" class=\"e-tab\">\n {{ item.label }}\n <span v-if=\"item.count != null\" class=\"e-tab-count\">{{ item.count }}</span>\n </TabsTrigger>\n </TabsList>\n <TabsContent v-for=\"item in flat\" :key=\"item.id\" :value=\"item.id\" class=\"e-tabpanel\">\n <slot :name=\"item.id\" :item=\"item\"><slot name=\"panel\" :item=\"item\" /></slot>\n </TabsContent>\n </TabsRoot>\n</template>\n\n<style>\n@layer e.containers {\n .e-tablist {\n display: flex;\n flex: none;\n gap: 0;\n /* stylelint-disable-next-line declaration-block-no-redundant-longhand-properties -- the two axes are set apart */\n overflow-x: auto;\n overflow-y: hidden;\n scrollbar-width: none;\n }\n\n .e-tablist::-webkit-scrollbar {\n display: none;\n }\n\n /* Tabs are button-like: every tab is ringed and neighbours sit flush and share an edge, so only the outer ends of the row are rounded. The selected tab is outlined in the primary colour with a thick slab along its bottom. */\n .e-tab {\n --e-bc: var(--e-border-strong);\n\n /* A selected tab rises: the slab is a band the tab paints along one edge itself, so there is no second shape behind the corners. Every tab is one control height tall either way. */\n --e-lift: 0px;\n --e-band: calc(var(--e-lift) + var(--e-stroke-edge));\n --e-slab: var(--e-primary);\n\n position: relative;\n display: inline-flex;\n align-items: center;\n gap: var(--e-space-2);\n flex: none;\n height: var(--e-control-height);\n padding: 0 var(--e-space-4) var(--e-lift);\n border: 0;\n border-radius: 0;\n background: transparent;\n box-shadow: inset 0 0 0 var(--e-stroke-edge) var(--e-bc);\n color: var(--e-muted);\n font: 500 var(--e-text-md) / 1 var(--e-font-sans);\n cursor: pointer;\n transition:\n color var(--e-duration-tap) var(--e-easing-out),\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 /* Only the outer ends of the row are rounded. */\n .e-tab:first-child {\n border-start-start-radius: var(--e-radius-md);\n border-end-start-radius: var(--e-radius-md);\n }\n\n .e-tab:last-child {\n border-start-end-radius: var(--e-radius-md);\n border-end-end-radius: var(--e-radius-md);\n }\n\n .e-tab + .e-tab {\n margin-inline-start: calc(-1 * var(--e-stroke-edge));\n }\n\n .e-tab:hover {\n --e-bc: var(--e-ink);\n\n z-index: var(--e-z-raised);\n color: var(--e-ink);\n background-color: var(--e-surface-hover);\n }\n\n .e-tab[aria-selected=\"true\"] {\n --e-bc: var(--e-primary);\n --e-lift: var(--e-depth);\n\n z-index: var(--e-z-sticky);\n background-color: color-mix(in srgb, var(--e-surface-tint), var(--e-ink) 3%);\n box-shadow:\n inset 0 0 0 var(--e-stroke-edge) var(--e-bc),\n inset 0 calc(-1 * var(--e-band)) 0 0 var(--e-slab);\n color: var(--e-ink);\n font-weight: 600;\n }\n\n /* The slab answers the pointer too: it darkens under the cursor, in step with the face. */\n .e-tab[aria-selected=\"true\"]:hover {\n --e-slab: color-mix(in srgb, var(--e-primary), var(--e-shade-slab));\n }\n\n .e-tab:focus-visible {\n z-index: var(--e-z-focus);\n outline: var(--e-stroke-focus) solid var(--e-focus-ring);\n outline-offset: var(--e-focus-gap);\n }\n\n .e-tabs--fill > .e-tablist {\n overflow-x: hidden;\n }\n\n .e-tabs--fill > .e-tablist > .e-tab {\n flex: 1 1 0;\n min-width: 0;\n justify-content: center;\n padding-inline: var(--e-space-1);\n }\n\n /* Vertical: the tabs stack beside the panel, flush and sharing edges. The selected tab rises towards the panel, so its slab is a band down the inline-start side, away from the panel, instead of along the bottom, and only the top and bottom ends of the column are rounded. */\n .e-tabs--vertical {\n display: flex;\n align-items: flex-start;\n gap: var(--e-space-4);\n }\n\n .e-tabs--vertical > .e-tablist {\n flex-direction: column;\n flex: none;\n overflow: visible;\n }\n\n .e-tabs--vertical > .e-tablist > .e-tab {\n --e-lift: 0px;\n\n height: var(--e-control-height);\n padding-block-end: 0;\n justify-content: flex-start;\n border-radius: 0;\n }\n\n .e-tabs--vertical > .e-tablist > .e-tab:first-child {\n border-start-start-radius: var(--e-radius-md);\n border-start-end-radius: var(--e-radius-md);\n }\n\n .e-tabs--vertical > .e-tablist > .e-tab:last-child {\n border-end-start-radius: var(--e-radius-md);\n border-end-end-radius: var(--e-radius-md);\n }\n\n .e-tabs--vertical > .e-tablist > .e-tab + .e-tab {\n margin-inline-start: 0;\n margin-block-start: calc(-1 * var(--e-stroke-edge));\n }\n\n .e-tabs--vertical > .e-tablist > .e-tab[aria-selected=\"true\"] {\n --e-lift: var(--e-depth);\n\n padding-inline-start: calc(var(--e-space-4) + var(--e-lift));\n box-shadow:\n inset 0 0 0 var(--e-stroke-edge) var(--e-bc),\n inset var(--e-band) 0 0 0 var(--e-slab);\n }\n\n .e-tabs--vertical > .e-tabpanel {\n flex: 1 1 0;\n min-width: 0;\n padding-top: 0;\n }\n\n :dir(rtl) .e-tabs--vertical > .e-tablist > .e-tab[aria-selected=\"true\"] {\n box-shadow:\n inset 0 0 0 var(--e-stroke-edge) var(--e-bc),\n inset calc(-1 * var(--e-band)) 0 0 0 var(--e-slab);\n }\n\n /* Framed: tabs and panel are one outlined card. The tab row sits over the panel's edge by one stroke, so a tab's lower edge and the panel's upper edge are the same line; the chosen tab has no edge on that side and its fill covers the panel's, opening into it. Tabs sit flush with their neighbours, square where they meet; only the card's outer corner at the first tab is rounded, and the panel's own corner beside it is square. The row always leaves a corner's width of open edge past the last tab, so the panel's curve never lands against a tab's straight edge. */\n .e-tabs--framed > .e-tablist {\n position: relative;\n z-index: var(--e-z-raised);\n margin-block-end: calc(-1 * var(--e-stroke-edge));\n }\n\n .e-tabs--framed > .e-tablist > .e-tab {\n --e-bc: var(--e-border-strong);\n --e-lift: 0px;\n\n border-radius: 0;\n background-color: var(--e-surface-tint);\n }\n\n .e-tabs--framed > .e-tablist > .e-tab:first-child {\n border-start-start-radius: var(--e-radius-md);\n }\n\n .e-tabs--framed.e-tabs--fill > .e-tablist > .e-tab:last-child {\n border-start-end-radius: var(--e-radius-md);\n }\n\n .e-tabs:not(.e-tabs--fill, .e-tabs--vertical).e-tabs--framed > .e-tablist {\n padding-inline-end: var(--e-radius-md);\n }\n\n .e-tabs--framed > .e-tablist > .e-tab:hover {\n background-color: var(--e-surface-hover);\n }\n\n /* The chosen tab rises like a button does, with its primary slab as a band on the edge away from the panel, and its open sides outlined in the primary colour. */\n .e-tabs--framed > .e-tablist > .e-tab[aria-selected=\"true\"] {\n --e-bc: var(--e-primary);\n --e-lift: var(--e-depth);\n\n padding-block: var(--e-lift) 0;\n background-color: var(--e-surface);\n box-shadow:\n inset var(--e-stroke-edge) 0 0 0 var(--e-bc),\n inset calc(-1 * var(--e-stroke-edge)) 0 0 0 var(--e-bc),\n inset 0 var(--e-band) 0 0 var(--e-slab);\n }\n\n .e-tabs--framed > .e-tabpanel {\n padding: var(--e-space-4);\n border-radius: var(--e-radius-md);\n border-start-start-radius: 0;\n background: var(--e-surface);\n box-shadow: inset 0 0 0 var(--e-stroke-edge) var(--e-border-strong);\n }\n\n .e-tabs--framed.e-tabs--fill > .e-tabpanel {\n border-start-end-radius: 0;\n }\n\n .e-tabs--framed.e-tabs--vertical {\n gap: 0;\n align-items: stretch;\n }\n\n .e-tabs--framed.e-tabs--vertical > .e-tablist {\n align-self: flex-start;\n margin-block-end: var(--e-radius-md);\n margin-inline-end: calc(-1 * var(--e-stroke-edge));\n }\n\n .e-tabs--framed.e-tabs--vertical > .e-tablist > .e-tab {\n border-radius: 0;\n }\n\n .e-tabs--framed.e-tabs--vertical > .e-tablist > .e-tab:first-child {\n border-start-start-radius: var(--e-radius-md);\n }\n\n .e-tabs--framed.e-tabs--vertical > .e-tablist > .e-tab[aria-selected=\"true\"] {\n margin-block: calc(-1 * var(--e-stroke-edge)) 0;\n padding-block: 0;\n padding-inline-start: calc(var(--e-space-4) + var(--e-lift));\n box-shadow:\n inset 0 var(--e-stroke-edge) 0 0 var(--e-bc),\n inset 0 calc(-1 * var(--e-stroke-edge)) 0 0 var(--e-bc),\n inset var(--e-band) 0 0 0 var(--e-slab);\n }\n\n :dir(rtl) .e-tabs--framed.e-tabs--vertical > .e-tablist > .e-tab[aria-selected=\"true\"] {\n box-shadow:\n inset 0 var(--e-stroke-edge) 0 0 var(--e-bc),\n inset 0 calc(-1 * var(--e-stroke-edge)) 0 0 var(--e-bc),\n inset calc(-1 * var(--e-band)) 0 0 0 var(--e-slab);\n }\n\n .e-tabs--framed.e-tabs--vertical > .e-tablist > .e-tab[aria-selected=\"true\"]:first-child {\n margin-block-start: 0;\n }\n\n .e-tabs--framed.e-tabs--vertical > .e-tabpanel {\n padding: var(--e-space-4);\n }\n\n .e-tab-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 color: var(--e-ink);\n }\n\n .e-tabpanel {\n padding-top: var(--e-space-4);\n }\n\n @media (prefers-reduced-motion: reduce) {\n .e-tab {\n transition: none;\n }\n }\n\n @media (forced-colors: active) {\n .e-tab[aria-selected=\"true\"] {\n forced-color-adjust: none;\n background: Highlight;\n color: HighlightText;\n }\n }\n}\n</style>\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;EAiBA,IAAMkB,IAAQC,GAiBRC,IAAOC,QAAeH,EAAM,SAAS,CAAC,CAAC,GAGvCI,IAAQtB,EAAmBmB,GAAA,YAAC,GAE5BK,IAASC,EAAU,GACnBC,IAAUL,QAAeC,EAAM,SAASF,EAAK,MAAM,EAAE,EAAE,EAAE,GACzDO,IAAMN,QACJG,EAAO,QAAQ,OAAO,WAAa,OAAe,SAAS,gBAAgB,QAAQ,QAAQ,QAAQ,MAC3G,GAEMI,IAAOC,EAAiC,IAAI;EAElD,eAAeC,EAAO,GAAiB;GACrC,MAAMC,EAAS;GACf,IAAMC,IAAKJ,EAAK,OAAO,KACjBK,IAAMD,GAAI,cAA2B,0BAAwB;GACnE,IAAId,EAAM,gBAAgB,cAAc,CAACc,KAAM,CAACC,KAAOD,EAAG,eAAeA,EAAG,aAAa;GACzF,IAAME,IAAO,OAAO,aAAe,OAAe,WAAW,kCAAkC,CAAC,CAAC,SAC3FC,IAAIF,EAAI,sBAAsB,GAC9BG,IAAIJ,EAAG,sBAAsB;GACnC,EAAG,SAAS;IAAE,MAAMG,EAAE,OAAOA,EAAE,QAAQ,KAAKC,EAAE,OAAOA,EAAE,QAAQ;IAAI,UAAUC,KAAU,CAACH,IAAO,WAAW;GAAO,CAAC;EACpH;E,OAEAI,QAAgBR,EAAO,EAAK,CAAC,GAC7BS,EAAMb,SAAeI,EAAO,EAAI,CAAC,I,UAI/B7B,EAAA,GAAAC,EAiBWC,EAAAwC,CAAA,GAAA;GAhBT,OAAKvC,EAAA,CAAC,UAAQ;IAAA,gBACYe,EAAA;IAAI,oBAAsBA,EAAA,gBAAW;IAAA,kBAAmCA,EAAA;GAAM,CAAA,CAAA;GACvG,aAAaA,EAAA,eAAW;GACxB,eAAaO,EAAA;GACb,KAAKC,EAAA;GACL,uBAAkB,AAAAkB,EAAA,QAAA,MAAE,EAAA,QAAQ,OAAOC,CAAM;;GAE1C,SAAAzC,QAKW,CALXC,EAKWH,EAAA8C,CAAA,GAAA;IALG,SAAA;IAAJ,KAAIrB;IAAO,OAAM;;IACZ,SAAAvB,QAAoB,EAAjCJ,EAAA,EAAA,GAAAM,EAGcC,GAAA,MAAAC,EAHcW,EAAA,QAAR,OAApBnB,EAAA,GAAAC,EAGcC,EAAAkD,CAAA,GAAA;KAHqB,KAAKC,EAAK;KAAK,OAAOA,EAAK;KAAI,OAAM;;KACtE,SAAAjD,QAAgB,CAAbK,EAAAC,EAAA2C,EAAK,KAAK,IAAG,KAChB,CAAA,GAAYA,EAAK,SAAK,O,aAAtBrD,EAAA,GAAAM,EAA2E,QAA3EO,GAA2EH,EAApB2C,EAAK,KAAK,GAAA,CAAA,E;;;;G,UAGrErD,EAAA,EAAA,GAAAM,EAEcC,GAAA,MAAAC,EAFcW,EAAA,QAAR,OAApBnB,EAAA,GAAAC,EAEcC,EAAAuD,CAAA,GAAA;IAFqB,KAAKJ,EAAK;IAAK,OAAOA,EAAK;IAAI,OAAM;;IACtE,SAAAjD,QAA4E,CAA5EQ,EAA4E+C,EAAA,QAA/DN,EAAK,IAAE,EAAS,QAAI,SAA2C,CAAzCzC,EAAkC+C,EAAA,QAAA,SAAA,EAAR,QAAI,CAAA,C"}
package/dist/style.css CHANGED
@@ -3992,9 +3992,6 @@ a:any-link > .e-highlight {
3992
3992
  align-items: center;
3993
3993
  gap: var(--e-space-2) var(--e-space-4);
3994
3994
  }
3995
- .e-pagehead-titlerow > :not(.e-pagehead-title) {
3996
- margin-top: var(--e-space-1);
3997
- }
3998
3995
  }
3999
3996
  @layer e.reset, e.tokens, e.base, e.primitives, e.blocks, e.controls, e.composites, e.containers, e.page;
4000
3997
  @layer e.composites {
@@ -4955,10 +4952,10 @@ to {
4955
4952
  outline: var(--e-stroke-focus) solid var(--e-focus-ring);
4956
4953
  outline-offset: var(--e-focus-gap);
4957
4954
  }
4958
- .e-tabs--fill .e-tablist {
4955
+ .e-tabs--fill > .e-tablist {
4959
4956
  overflow-x: hidden;
4960
4957
  }
4961
- .e-tabs--fill .e-tab {
4958
+ .e-tabs--fill > .e-tablist > .e-tab {
4962
4959
  flex: 1 1 0;
4963
4960
  min-width: 0;
4964
4961
  justify-content: center;
@@ -4971,12 +4968,12 @@ to {
4971
4968
  align-items: flex-start;
4972
4969
  gap: var(--e-space-4);
4973
4970
  }
4974
- .e-tabs--vertical .e-tablist {
4971
+ .e-tabs--vertical > .e-tablist {
4975
4972
  flex-direction: column;
4976
4973
  flex: none;
4977
4974
  overflow: visible;
4978
4975
  }
4979
- .e-tabs--vertical .e-tab {
4976
+ .e-tabs--vertical > .e-tablist > .e-tab {
4980
4977
  --e-lift: 0px;
4981
4978
 
4982
4979
  height: var(--e-control-height);
@@ -4984,19 +4981,19 @@ to {
4984
4981
  justify-content: flex-start;
4985
4982
  border-radius: 0;
4986
4983
  }
4987
- .e-tabs--vertical .e-tab:first-child {
4984
+ .e-tabs--vertical > .e-tablist > .e-tab:first-child {
4988
4985
  border-start-start-radius: var(--e-radius-md);
4989
4986
  border-start-end-radius: var(--e-radius-md);
4990
4987
  }
4991
- .e-tabs--vertical .e-tab:last-child {
4988
+ .e-tabs--vertical > .e-tablist > .e-tab:last-child {
4992
4989
  border-end-start-radius: var(--e-radius-md);
4993
4990
  border-end-end-radius: var(--e-radius-md);
4994
4991
  }
4995
- .e-tabs--vertical .e-tab + .e-tab {
4992
+ .e-tabs--vertical > .e-tablist > .e-tab + .e-tab {
4996
4993
  margin-inline-start: 0;
4997
4994
  margin-block-start: calc(-1 * var(--e-stroke-edge));
4998
4995
  }
4999
- .e-tabs--vertical .e-tab[aria-selected="true"] {
4996
+ .e-tabs--vertical > .e-tablist > .e-tab[aria-selected="true"] {
5000
4997
  --e-lift: var(--e-depth);
5001
4998
 
5002
4999
  padding-inline-start: calc(var(--e-space-4) + var(--e-lift));
@@ -5004,45 +5001,45 @@ to {
5004
5001
  inset 0 0 0 var(--e-stroke-edge) var(--e-bc),
5005
5002
  inset var(--e-band) 0 0 0 var(--e-slab);
5006
5003
  }
5007
- .e-tabs--vertical .e-tabpanel {
5004
+ .e-tabs--vertical > .e-tabpanel {
5008
5005
  flex: 1 1 0;
5009
5006
  min-width: 0;
5010
5007
  padding-top: 0;
5011
5008
  }
5012
- :dir(rtl) .e-tabs--vertical .e-tab[aria-selected="true"] {
5009
+ :dir(rtl) .e-tabs--vertical > .e-tablist > .e-tab[aria-selected="true"] {
5013
5010
  box-shadow:
5014
5011
  inset 0 0 0 var(--e-stroke-edge) var(--e-bc),
5015
5012
  inset calc(-1 * var(--e-band)) 0 0 0 var(--e-slab);
5016
5013
  }
5017
5014
 
5018
5015
  /* Framed: tabs and panel are one outlined card. The tab row sits over the panel's edge by one stroke, so a tab's lower edge and the panel's upper edge are the same line; the chosen tab has no edge on that side and its fill covers the panel's, opening into it. Tabs sit flush with their neighbours, square where they meet; only the card's outer corner at the first tab is rounded, and the panel's own corner beside it is square. The row always leaves a corner's width of open edge past the last tab, so the panel's curve never lands against a tab's straight edge. */
5019
- .e-tabs--framed .e-tablist {
5016
+ .e-tabs--framed > .e-tablist {
5020
5017
  position: relative;
5021
5018
  z-index: var(--e-z-raised);
5022
5019
  margin-block-end: calc(-1 * var(--e-stroke-edge));
5023
5020
  }
5024
- .e-tabs--framed .e-tab {
5021
+ .e-tabs--framed > .e-tablist > .e-tab {
5025
5022
  --e-bc: var(--e-border-strong);
5026
5023
  --e-lift: 0px;
5027
5024
 
5028
5025
  border-radius: 0;
5029
5026
  background-color: var(--e-surface-tint);
5030
5027
  }
5031
- .e-tabs--framed .e-tab:first-child {
5028
+ .e-tabs--framed > .e-tablist > .e-tab:first-child {
5032
5029
  border-start-start-radius: var(--e-radius-md);
5033
5030
  }
5034
- .e-tabs--framed.e-tabs--fill .e-tab:last-child {
5031
+ .e-tabs--framed.e-tabs--fill > .e-tablist > .e-tab:last-child {
5035
5032
  border-start-end-radius: var(--e-radius-md);
5036
5033
  }
5037
- .e-tabs:not(.e-tabs--fill, .e-tabs--vertical).e-tabs--framed .e-tablist {
5034
+ .e-tabs:not(.e-tabs--fill, .e-tabs--vertical).e-tabs--framed > .e-tablist {
5038
5035
  padding-inline-end: var(--e-radius-md);
5039
5036
  }
5040
- .e-tabs--framed .e-tab:hover {
5037
+ .e-tabs--framed > .e-tablist > .e-tab:hover {
5041
5038
  background-color: var(--e-surface-hover);
5042
5039
  }
5043
5040
 
5044
5041
  /* The chosen tab rises like a button does, with its primary slab as a band on the edge away from the panel, and its open sides outlined in the primary colour. */
5045
- .e-tabs--framed .e-tab[aria-selected="true"] {
5042
+ .e-tabs--framed > .e-tablist > .e-tab[aria-selected="true"] {
5046
5043
  --e-bc: var(--e-primary);
5047
5044
  --e-lift: var(--e-depth);
5048
5045
 
@@ -5053,32 +5050,32 @@ to {
5053
5050
  inset calc(-1 * var(--e-stroke-edge)) 0 0 0 var(--e-bc),
5054
5051
  inset 0 var(--e-band) 0 0 var(--e-slab);
5055
5052
  }
5056
- .e-tabs--framed .e-tabpanel {
5053
+ .e-tabs--framed > .e-tabpanel {
5057
5054
  padding: var(--e-space-4);
5058
5055
  border-radius: var(--e-radius-md);
5059
5056
  border-start-start-radius: 0;
5060
5057
  background: var(--e-surface);
5061
5058
  box-shadow: inset 0 0 0 var(--e-stroke-edge) var(--e-border-strong);
5062
5059
  }
5063
- .e-tabs--framed.e-tabs--fill .e-tabpanel {
5060
+ .e-tabs--framed.e-tabs--fill > .e-tabpanel {
5064
5061
  border-start-end-radius: 0;
5065
5062
  }
5066
5063
  .e-tabs--framed.e-tabs--vertical {
5067
5064
  gap: 0;
5068
5065
  align-items: stretch;
5069
5066
  }
5070
- .e-tabs--framed.e-tabs--vertical .e-tablist {
5067
+ .e-tabs--framed.e-tabs--vertical > .e-tablist {
5071
5068
  align-self: flex-start;
5072
5069
  margin-block-end: var(--e-radius-md);
5073
5070
  margin-inline-end: calc(-1 * var(--e-stroke-edge));
5074
5071
  }
5075
- .e-tabs--framed.e-tabs--vertical .e-tab {
5072
+ .e-tabs--framed.e-tabs--vertical > .e-tablist > .e-tab {
5076
5073
  border-radius: 0;
5077
5074
  }
5078
- .e-tabs--framed.e-tabs--vertical .e-tab:first-child {
5075
+ .e-tabs--framed.e-tabs--vertical > .e-tablist > .e-tab:first-child {
5079
5076
  border-start-start-radius: var(--e-radius-md);
5080
5077
  }
5081
- .e-tabs--framed.e-tabs--vertical .e-tab[aria-selected="true"] {
5078
+ .e-tabs--framed.e-tabs--vertical > .e-tablist > .e-tab[aria-selected="true"] {
5082
5079
  margin-block: calc(-1 * var(--e-stroke-edge)) 0;
5083
5080
  padding-block: 0;
5084
5081
  padding-inline-start: calc(var(--e-space-4) + var(--e-lift));
@@ -5087,16 +5084,16 @@ to {
5087
5084
  inset 0 calc(-1 * var(--e-stroke-edge)) 0 0 var(--e-bc),
5088
5085
  inset var(--e-band) 0 0 0 var(--e-slab);
5089
5086
  }
5090
- :dir(rtl) .e-tabs--framed.e-tabs--vertical .e-tab[aria-selected="true"] {
5087
+ :dir(rtl) .e-tabs--framed.e-tabs--vertical > .e-tablist > .e-tab[aria-selected="true"] {
5091
5088
  box-shadow:
5092
5089
  inset 0 var(--e-stroke-edge) 0 0 var(--e-bc),
5093
5090
  inset 0 calc(-1 * var(--e-stroke-edge)) 0 0 var(--e-bc),
5094
5091
  inset calc(-1 * var(--e-band)) 0 0 0 var(--e-slab);
5095
5092
  }
5096
- .e-tabs--framed.e-tabs--vertical .e-tab[aria-selected="true"]:first-child {
5093
+ .e-tabs--framed.e-tabs--vertical > .e-tablist > .e-tab[aria-selected="true"]:first-child {
5097
5094
  margin-block-start: 0;
5098
5095
  }
5099
- .e-tabs--framed.e-tabs--vertical .e-tabpanel {
5096
+ .e-tabs--framed.e-tabs--vertical > .e-tabpanel {
5100
5097
  padding: var(--e-space-4);
5101
5098
  }
5102
5099
  .e-tab-count {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@eos-ui/vue",
3
- "version": "0.5.0",
3
+ "version": "0.5.1",
4
4
  "description": "Eos: accessible Vue 3 components for the Eos portal.",
5
5
  "type": "module",
6
6
  "license": "MIT",
@@ -57,7 +57,7 @@
57
57
  }
58
58
  },
59
59
  "dependencies": {
60
- "@eos-ui/tokens": "0.5.0",
60
+ "@eos-ui/tokens": "0.5.1",
61
61
  "@tanstack/vue-table": "^9.3.1",
62
62
  "@tanstack/vue-virtual": "^3.13.47",
63
63
  "@vueuse/core": "^15.0.0",