@vielzeug/refine 26.10.7 → 26.10.10
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +6 -0
- package/dist/accordion-item.cjs +2 -2
- package/dist/accordion-item.cjs.map +1 -1
- package/dist/accordion-item.js +6 -6
- package/dist/accordion-item.js.map +1 -1
- package/dist/accordion.cjs +2 -2
- package/dist/accordion.cjs.map +1 -1
- package/dist/accordion.js +2 -2
- package/dist/accordion.js.map +1 -1
- package/dist/alert.cjs +2 -2
- package/dist/alert.cjs.map +1 -1
- package/dist/alert.js +2 -2
- package/dist/alert.js.map +1 -1
- package/dist/avatar.cjs +3 -3
- package/dist/avatar.cjs.map +1 -1
- package/dist/avatar.js +2 -2
- package/dist/avatar.js.map +1 -1
- package/dist/badge.cjs +2 -2
- package/dist/badge.cjs.map +1 -1
- package/dist/badge.js +2 -2
- package/dist/badge.js.map +1 -1
- package/dist/box.cjs +2 -2
- package/dist/box.cjs.map +1 -1
- package/dist/box.js +2 -2
- package/dist/box.js.map +1 -1
- package/dist/button-group.cjs +2 -2
- package/dist/button-group.cjs.map +1 -1
- package/dist/button-group.js +2 -2
- package/dist/button-group.js.map +1 -1
- package/dist/button.cjs +9 -9
- package/dist/button.cjs.map +1 -1
- package/dist/button.js +8 -8
- package/dist/button.js.map +1 -1
- package/dist/card.cjs +2 -2
- package/dist/card.cjs.map +1 -1
- package/dist/card.js +2 -2
- package/dist/card.js.map +1 -1
- package/dist/carousel.cjs +6 -6
- package/dist/carousel.cjs.map +1 -1
- package/dist/carousel.js +6 -6
- package/dist/carousel.js.map +1 -1
- package/dist/chat-message.cjs +4 -4
- package/dist/chat-message.cjs.map +1 -1
- package/dist/chat-message.js +4 -4
- package/dist/chat-message.js.map +1 -1
- package/dist/checkbox-group.cjs +1 -1
- package/dist/checkbox-group.cjs.map +1 -1
- package/dist/checkbox-group.js +1 -1
- package/dist/checkbox-group.js.map +1 -1
- package/dist/checkbox.cjs +1 -1
- package/dist/checkbox.cjs.map +1 -1
- package/dist/checkbox.js +1 -1
- package/dist/checkbox.js.map +1 -1
- package/dist/chip.cjs +8 -8
- package/dist/chip.cjs.map +1 -1
- package/dist/chip.js +8 -8
- package/dist/chip.js.map +1 -1
- package/dist/combobox.cjs +8 -8
- package/dist/combobox.cjs.map +1 -1
- package/dist/combobox.js +11 -11
- package/dist/combobox.js.map +1 -1
- package/dist/content/avatar/avatar.d.ts +2 -1
- package/dist/content/avatar/avatar.d.ts.map +1 -1
- package/dist/content/card/card.d.ts +6 -3
- package/dist/content/card/card.d.ts.map +1 -1
- package/dist/content/carousel/carousel.d.ts +5 -3
- package/dist/content/carousel/carousel.d.ts.map +1 -1
- package/dist/content/chat-message/chat-message.d.ts +2 -1
- package/dist/content/chat-message/chat-message.d.ts.map +1 -1
- package/dist/content/copy-command/copy-command.d.ts +1 -1
- package/dist/content/copy-command/copy-command.d.ts.map +1 -1
- package/dist/content/keyboard-key/keyboard-key.d.ts +2 -1
- package/dist/content/keyboard-key/keyboard-key.d.ts.map +1 -1
- package/dist/content/list/list.d.ts +2 -1
- package/dist/content/list/list.d.ts.map +1 -1
- package/dist/content/marquee/marquee.d.ts +3 -2
- package/dist/content/marquee/marquee.d.ts.map +1 -1
- package/dist/content/pagination/pagination.d.ts +1 -1
- package/dist/content/pagination/pagination.d.ts.map +1 -1
- package/dist/content/qr-code/qr-code.d.ts +0 -41
- package/dist/content/qr-code/qr-code.d.ts.map +1 -1
- package/dist/content/separator/separator.d.ts +1 -1
- package/dist/content/separator/separator.d.ts.map +1 -1
- package/dist/content/stepper/step.d.ts +1 -1
- package/dist/content/stepper/step.d.ts.map +1 -1
- package/dist/content/table/table.d.ts +2 -1
- package/dist/content/table/table.d.ts.map +1 -1
- package/dist/content/text/text.d.ts +13 -6
- package/dist/content/text/text.d.ts.map +1 -1
- package/dist/cookie-banner.cjs +1 -1
- package/dist/cookie-banner.cjs.map +1 -1
- package/dist/cookie-banner.js +1 -1
- package/dist/cookie-banner.js.map +1 -1
- package/dist/copy-command.cjs +6 -6
- package/dist/copy-command.cjs.map +1 -1
- package/dist/copy-command.js +7 -7
- package/dist/copy-command.js.map +1 -1
- package/dist/core/checkable.cjs +1 -1
- package/dist/core/checkable.cjs.map +1 -1
- package/dist/core/checkable.d.ts +6 -7
- package/dist/core/checkable.d.ts.map +1 -1
- package/dist/core/checkable.js +1 -1
- package/dist/core/checkable.js.map +1 -1
- package/dist/core/choice-field.cjs +1 -1
- package/dist/core/choice-field.cjs.map +1 -1
- package/dist/core/choice-field.d.ts +6 -6
- package/dist/core/choice-field.d.ts.map +1 -1
- package/dist/core/choice-field.js +1 -1
- package/dist/core/choice-field.js.map +1 -1
- package/dist/core/text-field.cjs +1 -1
- package/dist/core/text-field.cjs.map +1 -1
- package/dist/core/text-field.d.ts +8 -8
- package/dist/core/text-field.d.ts.map +1 -1
- package/dist/core/text-field.js +1 -1
- package/dist/core/text-field.js.map +1 -1
- package/dist/counter.cjs +2 -2
- package/dist/counter.cjs.map +1 -1
- package/dist/counter.js +2 -2
- package/dist/counter.js.map +1 -1
- package/dist/custom-elements.json +886 -749
- package/dist/datagrid.cjs +47 -47
- package/dist/datagrid.cjs.map +1 -1
- package/dist/datagrid.js +51 -51
- package/dist/datagrid.js.map +1 -1
- package/dist/date-picker.cjs +9 -9
- package/dist/date-picker.cjs.map +1 -1
- package/dist/date-picker.js +11 -11
- package/dist/date-picker.js.map +1 -1
- package/dist/dialog.cjs +3 -3
- package/dist/dialog.cjs.map +1 -1
- package/dist/dialog.js +3 -3
- package/dist/dialog.js.map +1 -1
- package/dist/disclosure/accordion/accordion.d.ts +4 -2
- package/dist/disclosure/accordion/accordion.d.ts.map +1 -1
- package/dist/disclosure/accordion-item/accordion-item.d.ts +1 -1
- package/dist/disclosure/accordion-item/accordion-item.d.ts.map +1 -1
- package/dist/disclosure/tab-item/tab-item.d.ts +1 -1
- package/dist/disclosure/tab-item/tab-item.d.ts.map +1 -1
- package/dist/disclosure/tabs/tabs.d.ts +1 -1
- package/dist/disclosure/tabs/tabs.d.ts.map +1 -1
- package/dist/drawer.cjs +4 -4
- package/dist/drawer.cjs.map +1 -1
- package/dist/drawer.js +2 -2
- package/dist/drawer.js.map +1 -1
- package/dist/feedback/alert/alert.d.ts +2 -1
- package/dist/feedback/alert/alert.d.ts.map +1 -1
- package/dist/feedback/badge/badge.d.ts +7 -4
- package/dist/feedback/badge/badge.d.ts.map +1 -1
- package/dist/feedback/chip/chip.d.ts +7 -5
- package/dist/feedback/chip/chip.d.ts.map +1 -1
- package/dist/grid-item.cjs +2 -2
- package/dist/grid-item.cjs.map +1 -1
- package/dist/grid-item.js +2 -2
- package/dist/grid-item.js.map +1 -1
- package/dist/grid.cjs +2 -2
- package/dist/grid.cjs.map +1 -1
- package/dist/grid.js +2 -2
- package/dist/grid.js.map +1 -1
- package/dist/input.cjs +7 -7
- package/dist/input.cjs.map +1 -1
- package/dist/input.js +8 -8
- package/dist/input.js.map +1 -1
- package/dist/inputs/button/button.d.ts +3 -2
- package/dist/inputs/button/button.d.ts.map +1 -1
- package/dist/inputs/button-group/button-group.d.ts +1 -37
- package/dist/inputs/button-group/button-group.d.ts.map +1 -1
- package/dist/inputs/combobox/combobox.types.d.ts +2 -2
- package/dist/inputs/combobox/combobox.types.d.ts.map +1 -1
- package/dist/inputs/counter/counter.d.ts +3 -2
- package/dist/inputs/counter/counter.d.ts.map +1 -1
- package/dist/inputs/datagrid/datagrid-model.cjs +1 -1
- package/dist/inputs/datagrid/datagrid-model.cjs.map +1 -1
- package/dist/inputs/datagrid/datagrid-model.d.ts +2 -1
- package/dist/inputs/datagrid/datagrid-model.d.ts.map +1 -1
- package/dist/inputs/datagrid/datagrid-model.js +1 -1
- package/dist/inputs/datagrid/datagrid-model.js.map +1 -1
- package/dist/inputs/datagrid/datagrid.d.ts +4 -2
- package/dist/inputs/datagrid/datagrid.d.ts.map +1 -1
- package/dist/inputs/date-picker/date-picker.d.ts +3 -2
- package/dist/inputs/date-picker/date-picker.d.ts.map +1 -1
- package/dist/inputs/input/input.d.ts +5 -3
- package/dist/inputs/input/input.d.ts.map +1 -1
- package/dist/inputs/message-composer/message-composer.d.ts +3 -2
- package/dist/inputs/message-composer/message-composer.d.ts.map +1 -1
- package/dist/inputs/number-input/number-input.d.ts +1 -1
- package/dist/inputs/number-input/number-input.d.ts.map +1 -1
- package/dist/inputs/otp-input/otp-input.d.ts +3 -2
- package/dist/inputs/otp-input/otp-input.d.ts.map +1 -1
- package/dist/inputs/query-bar/query-bar.d.ts.map +1 -1
- package/dist/inputs/select/select.d.ts +2 -2
- package/dist/inputs/select/select.d.ts.map +1 -1
- package/dist/inputs/textarea/textarea.d.ts +4 -3
- package/dist/inputs/textarea/textarea.d.ts.map +1 -1
- package/dist/inputs/time-picker/time-picker.d.ts +2 -2
- package/dist/inputs/time-picker/time-picker.d.ts.map +1 -1
- package/dist/keyboard-key.cjs +3 -3
- package/dist/keyboard-key.cjs.map +1 -1
- package/dist/keyboard-key.js +3 -3
- package/dist/keyboard-key.js.map +1 -1
- package/dist/layout/box/box.d.ts +6 -3
- package/dist/layout/box/box.d.ts.map +1 -1
- package/dist/layout/grid/grid.d.ts +11 -6
- package/dist/layout/grid/grid.d.ts.map +1 -1
- package/dist/layout/grid-item/grid-item.d.ts +8 -4
- package/dist/layout/grid-item/grid-item.d.ts.map +1 -1
- package/dist/layout/navbar/navbar.d.ts +4 -2
- package/dist/layout/navbar/navbar.d.ts.map +1 -1
- package/dist/layout/sidebar/sidebar.d.ts +2 -1
- package/dist/layout/sidebar/sidebar.d.ts.map +1 -1
- package/dist/list-item.cjs +1 -1
- package/dist/list-item.cjs.map +1 -1
- package/dist/list-item.js +1 -1
- package/dist/list-item.js.map +1 -1
- package/dist/list.cjs +2 -2
- package/dist/list.cjs.map +1 -1
- package/dist/list.js +2 -2
- package/dist/list.js.map +1 -1
- package/dist/marquee.cjs +3 -3
- package/dist/marquee.cjs.map +1 -1
- package/dist/marquee.js +3 -3
- package/dist/marquee.js.map +1 -1
- package/dist/menu.cjs +3 -3
- package/dist/menu.cjs.map +1 -1
- package/dist/menu.js +3 -3
- package/dist/menu.js.map +1 -1
- package/dist/message-composer.cjs +10 -10
- package/dist/message-composer.cjs.map +1 -1
- package/dist/message-composer.js +7 -7
- package/dist/message-composer.js.map +1 -1
- package/dist/navbar.cjs +10 -10
- package/dist/navbar.cjs.map +1 -1
- package/dist/navbar.js +13 -13
- package/dist/navbar.js.map +1 -1
- package/dist/number-input.cjs +3 -3
- package/dist/number-input.cjs.map +1 -1
- package/dist/number-input.js +4 -4
- package/dist/number-input.js.map +1 -1
- package/dist/otp-input.cjs +4 -4
- package/dist/otp-input.cjs.map +1 -1
- package/dist/otp-input.js +4 -4
- package/dist/otp-input.js.map +1 -1
- package/dist/overlay/dialog/dialog.d.ts +7 -4
- package/dist/overlay/dialog/dialog.d.ts.map +1 -1
- package/dist/overlay/drawer/drawer.d.ts +4 -2
- package/dist/overlay/drawer/drawer.d.ts.map +1 -1
- package/dist/overlay/menu/menu.d.ts +2 -1
- package/dist/overlay/menu/menu.d.ts.map +1 -1
- package/dist/pagination.cjs +9 -9
- package/dist/pagination.cjs.map +1 -1
- package/dist/pagination.js +9 -9
- package/dist/pagination.js.map +1 -1
- package/dist/qr-code.cjs +2 -2
- package/dist/qr-code.cjs.map +1 -1
- package/dist/qr-code.js +2 -2
- package/dist/qr-code.js.map +1 -1
- package/dist/query-bar.cjs +7 -7
- package/dist/query-bar.cjs.map +1 -1
- package/dist/query-bar.js +8 -8
- package/dist/query-bar.js.map +1 -1
- package/dist/radio-group.cjs +1 -1
- package/dist/radio-group.cjs.map +1 -1
- package/dist/radio-group.js +1 -1
- package/dist/radio-group.js.map +1 -1
- package/dist/refine.cjs +123 -123
- package/dist/refine.cjs.map +1 -1
- package/dist/refine.iife.js +123 -123
- package/dist/refine.iife.js.map +1 -1
- package/dist/refine.js +124 -124
- package/dist/refine.js.map +1 -1
- package/dist/select.cjs +13 -13
- package/dist/select.cjs.map +1 -1
- package/dist/select.js +15 -15
- package/dist/select.js.map +1 -1
- package/dist/separator.cjs +4 -4
- package/dist/separator.cjs.map +1 -1
- package/dist/separator.js +4 -4
- package/dist/separator.js.map +1 -1
- package/dist/shared/prop-bundles.cjs +1 -1
- package/dist/shared/prop-bundles.cjs.map +1 -1
- package/dist/shared/prop-bundles.d.ts +7 -8
- package/dist/shared/prop-bundles.d.ts.map +1 -1
- package/dist/shared/prop-bundles.js +1 -1
- package/dist/shared/prop-bundles.js.map +1 -1
- package/dist/shared/types.cjs +2 -0
- package/dist/shared/types.cjs.map +1 -0
- package/dist/shared/types.d.ts +27 -9
- package/dist/shared/types.d.ts.map +1 -1
- package/dist/shared/types.js +2 -0
- package/dist/shared/types.js.map +1 -0
- package/dist/sidebar.cjs +7 -7
- package/dist/sidebar.cjs.map +1 -1
- package/dist/sidebar.js +4 -4
- package/dist/sidebar.js.map +1 -1
- package/dist/step.cjs +10 -10
- package/dist/step.cjs.map +1 -1
- package/dist/step.js +10 -10
- package/dist/step.js.map +1 -1
- package/dist/tab-item.cjs +4 -4
- package/dist/tab-item.cjs.map +1 -1
- package/dist/tab-item.js +5 -5
- package/dist/tab-item.js.map +1 -1
- package/dist/table.cjs +2 -2
- package/dist/table.cjs.map +1 -1
- package/dist/table.js +2 -2
- package/dist/table.js.map +1 -1
- package/dist/tabs.cjs +2 -2
- package/dist/tabs.cjs.map +1 -1
- package/dist/tabs.js +4 -4
- package/dist/tabs.js.map +1 -1
- package/dist/text.cjs +2 -2
- package/dist/text.cjs.map +1 -1
- package/dist/text.js +2 -2
- package/dist/text.js.map +1 -1
- package/dist/textarea.cjs +7 -7
- package/dist/textarea.cjs.map +1 -1
- package/dist/textarea.js +7 -7
- package/dist/textarea.js.map +1 -1
- package/dist/time-picker.cjs +7 -7
- package/dist/time-picker.cjs.map +1 -1
- package/dist/time-picker.js +7 -7
- package/dist/time-picker.js.map +1 -1
- package/dist/tooltip.cjs +1 -1
- package/dist/tooltip.cjs.map +1 -1
- package/dist/tooltip.js +1 -1
- package/dist/tooltip.js.map +1 -1
- package/package.json +15 -14
package/dist/step.cjs
CHANGED
|
@@ -1,20 +1,20 @@
|
|
|
1
|
-
Object.defineProperty(exports,Symbol.toStringTag,{value:`Module`});const e=require("./styles/mixins/accessibility.css.cjs"),t=require("./styles/mixins/theme.css.cjs"),n=require("./shared/prop-bundles.cjs"),
|
|
1
|
+
Object.defineProperty(exports,Symbol.toStringTag,{value:`Module`});const e=require("./styles/mixins/accessibility.css.cjs"),t=require("./styles/mixins/theme.css.cjs"),n=require("./shared/types.cjs"),r=require("./shared/prop-bundles.cjs"),i=require("./icon.cjs"),a=require("./content/stepper/_is-step-navigable.cjs"),o=require("./content/stepper/step.css.cjs"),s=require("./stepper.cjs");let c=require("@vielzeug/ore");var l=`ore-step`;(0,c.define)(l,{props:{...r.disablableBundle,color:c.prop.oneOf(n.THEME_COLORS),error:c.prop.bool(!1),optional:c.prop.bool(!1),orientation:c.prop.oneOf([`horizontal`,`vertical`],`horizontal`),size:c.prop.oneOf(n.COMPONENT_SIZES),value:c.prop.string(``)},setup(e){let t=(0,c.getHost)(),n=(0,c.useSlots)(),r=(0,c.inject)(s.STEPPER_CTX),stepIndex=()=>r?r.stepValues.value.indexOf(e.value.value):-1,totalSteps=()=>r?.stepValues.value.length??0,currentIndex=()=>r?r.stepValues.value.indexOf(r.currentValue.value??``):-1,displayIndex=()=>{let e=stepIndex();return e>=0?e+1:1},displayTotal=()=>totalSteps()||1,isCurrent=()=>{let e=stepIndex(),t=currentIndex();return e>=0&&e===t},isCompleted=()=>{let e=stepIndex(),t=currentIndex();return e>=0&&t>=0&&e<t},isNavigable=()=>{let t=stepIndex(),n=currentIndex();return!!r&&a.isStepNavigable({disabled:e.disabled.value===!0,index:t,linear:r.linear.value,stepperClickable:r.clickable.value,stepperCurrentIndex:n})},isDisabled=()=>!!e.disabled.value;(0,c.bind)({attr:{completed:()=>isCompleted()?!0:void 0,current:()=>isCurrent()?!0:void 0,index:()=>{let e=stepIndex();return e>=0?String(e+1):void 0},navigable:()=>isNavigable()?!0:void 0,total:()=>r?String(totalSteps()):void 0}}),r&&(0,c.watchEffect)(()=>{let e=r.color.value,n=r.size.value,i=r.orientation.value;e!==void 0&&t.setAttribute(`color`,e),n!==void 0&&t.setAttribute(`size`,n),t.setAttribute(`orientation`,i)});let stateLabel=()=>{if(e.error.value)return`error`;if(isCompleted())return`completed`;if(isCurrent())return`current step`},positionLabel=()=>`Step ${displayIndex()} of ${displayTotal()}`,srLabel=()=>{let e=stateLabel();return e?`${positionLabel()}, ${e}`:positionLabel()},handleClick=n=>{if(n.stopPropagation(),!isNavigable()){n.preventDefault();return}t.dispatchEvent(new CustomEvent(`click`,{bubbles:!0,detail:{value:e.value.value}}))},indicatorTemplate=()=>c.html`
|
|
2
2
|
<span class="indicator" part="indicator" aria-hidden="true">
|
|
3
3
|
<span class="icon-slot" ?hidden="${()=>!n.has(`icon`).value}"><slot name="icon"></slot></span>
|
|
4
|
-
${()=>n.has(`icon`).value?``:e.error.value?
|
|
4
|
+
${()=>n.has(`icon`).value?``:e.error.value?c.html`
|
|
5
5
|
<ore-icon name="x" size="14" stroke-width="3"></ore-icon>
|
|
6
|
-
`:isCompleted()?
|
|
6
|
+
`:isCompleted()?c.html`
|
|
7
7
|
<ore-icon name="check" size="14" stroke-width="3"></ore-icon>
|
|
8
|
-
`:
|
|
8
|
+
`:c.html`
|
|
9
9
|
<span class="number">${displayIndex}</span>
|
|
10
10
|
`}
|
|
11
11
|
</span>
|
|
12
|
-
`,contentTemplate=()=>
|
|
12
|
+
`,contentTemplate=()=>c.html`
|
|
13
13
|
<span class="content" part="content">
|
|
14
14
|
<span class="sr-only">${srLabel}</span>
|
|
15
15
|
<span class="label" part="label">
|
|
16
16
|
<span class="label-text"><slot></slot></span>
|
|
17
|
-
${()=>e.optional.value?
|
|
17
|
+
${()=>e.optional.value?c.html`
|
|
18
18
|
<span class="optional-hint">(optional)</span>
|
|
19
19
|
`:``}
|
|
20
20
|
</span>
|
|
@@ -22,11 +22,11 @@ Object.defineProperty(exports,Symbol.toStringTag,{value:`Module`});const e=requi
|
|
|
22
22
|
<slot name="description"></slot>
|
|
23
23
|
</span>
|
|
24
24
|
</span>
|
|
25
|
-
`;return
|
|
25
|
+
`;return c.html`
|
|
26
26
|
<li class="step" role="listitem">
|
|
27
27
|
<span class="connector connector-leading" part="connector" aria-hidden="true"></span>
|
|
28
28
|
<span class="connector connector-trailing" part="connector" aria-hidden="true"></span>
|
|
29
|
-
${()=>isNavigable()?
|
|
29
|
+
${()=>isNavigable()?c.html`
|
|
30
30
|
<button
|
|
31
31
|
type="button"
|
|
32
32
|
class="control"
|
|
@@ -37,11 +37,11 @@ Object.defineProperty(exports,Symbol.toStringTag,{value:`Module`});const e=requi
|
|
|
37
37
|
@click="${handleClick}">
|
|
38
38
|
${indicatorTemplate()}${contentTemplate()}
|
|
39
39
|
</button>
|
|
40
|
-
`:
|
|
40
|
+
`:c.html`
|
|
41
41
|
<div class="control" part="control" aria-current="${()=>isCurrent()?`step`:null}">
|
|
42
42
|
${indicatorTemplate()}${contentTemplate()}
|
|
43
43
|
</div>
|
|
44
44
|
`}
|
|
45
45
|
</li>
|
|
46
|
-
`},styles:[t.colorThemeMixin,e.coarsePointerMixin,t.forcedColorsFocusMixin(`button.control`),
|
|
46
|
+
`},styles:[t.colorThemeMixin,e.coarsePointerMixin,t.forcedColorsFocusMixin(`button.control`),o.default]}),exports.ICON_TAG=i.ICON_TAG,exports.STEP_TAG=l;
|
|
47
47
|
//# sourceMappingURL=step.cjs.map
|
package/dist/step.cjs.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"step.cjs","names":[],"sources":["../src/content/stepper/step.ts"],"sourcesContent":["import { bind, define, getHost, html, inject, prop, useSlots, watchEffect } from '@vielzeug/ore';\nimport { disablableBundle } from '../../shared';\nimport { coarsePointerMixin, colorThemeMixin, forcedColorsFocusMixin } from '../../styles';\nimport type { ComponentSize, ThemeColor } from '../../types';\nimport { isStepNavigable } from './_is-step-navigable';\nimport stepStyles from './step.css?inline';\nimport { STEPPER_CTX } from './stepper';\n\nexport { ICON_TAG } from '../icon/icon';\nexport type OreStepProps = {\n /**\n * Theme color. Inherited from the parent `ore-stepper` when nested inside one (overrides\n * this value); only takes effect on its own when `ore-step` is rendered standalone.\n */\n color?: ThemeColor;\n /** Disables this step: it cannot be navigated to and is skipped by keyboard navigation. */\n disabled?: boolean;\n /** Marks this step as failed/invalid. Overrides the completed/current indicator visuals. */\n error?: boolean;\n /**\n * Marks this step as optional. Renders a small \"(optional)\" hint next to the label.\n * Purely presentational: has no effect on navigation.\n */\n optional?: boolean;\n /** Orientation. Inherited from the parent `ore-stepper` when nested inside one. */\n orientation?: 'horizontal' | 'vertical';\n /** Component size. Inherited from the parent `ore-stepper` when nested inside one. */\n size?: ComponentSize;\n /** Unique identifier, matches `ore-stepper`'s `value` attribute. */\n value: string;\n};\n\n/**\n * A single step trigger. Must be placed as a direct child of `ore-stepper`, which provides\n * this step's current/completed/navigable/index/total state via context: those are derived,\n * read-only attributes on this element, not settable props.\n *\n * @element ore-step\n *\n * @attr {string} value - Unique identifier, matches the parent ore-stepper's `value` attribute\n * @attr {boolean} disabled - Prevents navigation to this step\n * @attr {boolean} error - Marks the step as failed/invalid\n * @attr {boolean} optional - Renders an \"(optional)\" hint next to the label\n * @attr {boolean} current - Read-only. Derived from position relative to the parent ore-stepper's `value`.\n * @attr {boolean} completed - Read-only. Derived from position relative to the parent ore-stepper's `value`.\n * @attr {boolean} navigable - Read-only. Derived from the parent ore-stepper's `clickable`/`linear`/`disabled`.\n * @attr {number} index - Read-only. This step's 1-based position among its siblings.\n * @attr {number} total - Read-only. Total sibling step count.\n * @attr {string} color - Inherited from ore-stepper: 'primary' | 'secondary' | 'info' | 'success' | 'warning' | 'error'\n * @attr {string} size - Inherited from ore-stepper: 'sm' | 'md' | 'lg'\n * @attr {string} orientation - Inherited from ore-stepper: 'horizontal' | 'vertical'\n *\n * @slot - Step label\n * @slot description - Optional supporting text shown below the label\n * @slot icon - Custom icon replacing the step number/check/error indicator\n *\n * @part control - Clickable (or static) root element for the step\n * @part indicator - Circular indicator holding the number/icon\n * @part content - Wrapper around the label and description\n * @part label - Step label element\n * @part description - Step description element\n * @part connector - Connector line segments (leading and trailing halves) either side of this step's indicator\n *\n * @example\n * ```html\n * <ore-step value=\"details\">Account details</ore-step>\n * <ore-step value=\"review\" disabled>Review</ore-step>\n * ```\n */\nexport const STEP_TAG = 'ore-step' as const;\ndefine<OreStepProps>(STEP_TAG, {\n props: {\n ...disablableBundle,\n color: prop.string<ThemeColor>(),\n error: prop.bool(false),\n optional: prop.bool(false),\n orientation: prop.oneOf(['horizontal', 'vertical'] as const, 'horizontal'),\n size: prop.string<ComponentSize>(),\n value: prop.string(''),\n },\n setup(props) {\n const el = getHost();\n const slots = useSlots();\n const stepperCtx = inject(STEPPER_CTX);\n\n // ────────────────────────────────────────────────────────────────\n // State derived from the parent ore-stepper's context: see stepper.ts's\n // module doc comment for why this replaced parent-side attribute fan-out.\n // ────────────────────────────────────────────────────────────────\n\n // Plain functions, not `computed()`: every one of these ultimately reads\n // `stepperCtx.stepValues`/`stepperCtx.currentValue`, which are themselves `computed()`s\n // owned by the parent `ore-stepper`. Wrapping a *child* `computed()` around a *parent*\n // `computed()` (a computed-to-computed dependency crossing a `provide()`/`inject()`\n // boundary) is exactly the shape that surfaced two related bugs: a step's `completed`/\n // `current` attributes going permanently stale after a few rapid selections, and: worse :\n // a step's entire clickable/static control silently failing to render at all when its\n // `ore-step` tag upgrades before its siblings exist in the light DOM yet (true whenever\n // `ore-step`/`ore-stepper` are already `customElements.define()`d before this markup is\n // parsed, e.g. every sandboxed live-preview iframe). Reading straight through to the\n // parent's computeds on every call: no intermediate computed layer of our own to go\n // stale: made both disappear. Cheap enough to not need memoizing (a couple of `indexOf`/\n // comparisons over an already-memoized parent computed).\n const stepIndex = (): number => (stepperCtx ? stepperCtx.stepValues.value.indexOf(props.value.value) : -1);\n const totalSteps = (): number => stepperCtx?.stepValues.value.length ?? 0;\n const currentIndex = (): number =>\n stepperCtx ? stepperCtx.stepValues.value.indexOf(stepperCtx.currentValue.value ?? '') : -1;\n // 1-based, always-sane values for on-screen text (the step number badge, the sr-only\n // \"Step X of Y\" label): falls back to \"1 of 1\" when rendered standalone with no parent\n // `ore-stepper` to derive a real position from. Kept separate from the `index`/`total`\n // *attributes* below, which correctly reflect nothing at all in that same standalone case.\n const displayIndex = (): number => {\n const index = stepIndex();\n\n return index >= 0 ? index + 1 : 1;\n };\n const displayTotal = (): number => totalSteps() || 1;\n\n const isCurrent = (): boolean => {\n const index = stepIndex();\n const current = currentIndex();\n\n return index >= 0 && index === current;\n };\n // Purely positional: intentionally NOT gated on `props.error.value`. This also drives the\n // `completed` *attribute* below, which `step.css` uses to color both connector segments\n // either side of the indicator (`:host([completed]) .connector`); every *consumer* of this\n // (the icon choice, the sr-only state label) already checks `error` first and short-circuits\n // before it matters, so folding `!error` in here too would only end up suppressing\n // `[completed]` on an error step that's before the current one: breaking the connector\n // color chain right at that step instead of just swapping its icon.\n const isCompleted = (): boolean => {\n const index = stepIndex();\n const current = currentIndex();\n\n return index >= 0 && current >= 0 && index < current;\n };\n const isNavigable = (): boolean => {\n const index = stepIndex();\n const current = currentIndex();\n\n return (\n !!stepperCtx &&\n isStepNavigable({\n disabled: props.disabled.value === true,\n index,\n linear: stepperCtx.linear.value,\n stepperClickable: stepperCtx.clickable.value,\n stepperCurrentIndex: current,\n })\n );\n };\n const isDisabled = () => Boolean(props.disabled.value);\n\n // Purely derived, read-only state: no matching `prop.*` declaration, so `bind()` is the\n // sole writer and can safely reflect `undefined` (removes the attribute) when this step\n // isn't nested inside an `ore-stepper` at all.\n bind({\n attr: {\n completed: () => (isCompleted() ? true : undefined),\n current: () => (isCurrent() ? true : undefined),\n index: () => {\n const index = stepIndex();\n\n return index >= 0 ? String(index + 1) : undefined;\n },\n navigable: () => (isNavigable() ? true : undefined),\n total: () => (stepperCtx ? String(totalSteps()) : undefined),\n },\n });\n\n // `color`/`size`/`orientation` double as regular, independently-settable props (for a step\n // rendered standalone) *and* stepper-inherited values: mirrors ore-tab-item's handling of\n // its own `color`/`size`/`variant` inheritance from `ore-tabs`. Only forcibly overwrite the\n // attribute when a parent context actually exists, so the plain prop reflection is left\n // alone otherwise.\n if (stepperCtx) {\n watchEffect(() => {\n const color = stepperCtx.color.value;\n const size = stepperCtx.size.value;\n const orientation = stepperCtx.orientation.value;\n\n if (color !== undefined) el.setAttribute('color', color);\n\n if (size !== undefined) el.setAttribute('size', size);\n\n el.setAttribute('orientation', orientation);\n });\n }\n\n const stateLabel = (): string | undefined => {\n if (props.error.value) return 'error';\n\n if (isCompleted()) return 'completed';\n\n if (isCurrent()) return 'current step';\n\n return undefined;\n };\n\n const positionLabel = () => `Step ${displayIndex()} of ${displayTotal()}`;\n const srLabel = () => {\n const state = stateLabel();\n\n return state ? `${positionLabel()}, ${state}` : positionLabel();\n };\n\n const handleClick = (event: MouseEvent) => {\n event.stopPropagation();\n\n if (!isNavigable()) {\n event.preventDefault();\n\n return;\n }\n\n el.dispatchEvent(new CustomEvent('click', { bubbles: true, detail: { value: props.value.value } }));\n };\n\n const indicatorTemplate = () => html`\n <span class=\"indicator\" part=\"indicator\" aria-hidden=\"true\">\n <span class=\"icon-slot\" ?hidden=\"${() => !slots.has('icon').value}\"><slot name=\"icon\"></slot></span>\n ${() =>\n slots.has('icon').value\n ? ''\n : props.error.value\n ? html`\n <ore-icon name=\"x\" size=\"14\" stroke-width=\"3\"></ore-icon>\n `\n : isCompleted()\n ? html`\n <ore-icon name=\"check\" size=\"14\" stroke-width=\"3\"></ore-icon>\n `\n : html`\n <span class=\"number\">${displayIndex}</span>\n `}\n </span>\n `;\n\n const contentTemplate = () => html`\n <span class=\"content\" part=\"content\">\n <span class=\"sr-only\">${srLabel}</span>\n <span class=\"label\" part=\"label\">\n <span class=\"label-text\"><slot></slot></span>\n ${() =>\n props.optional.value\n ? html`\n <span class=\"optional-hint\">(optional)</span>\n `\n : ''}\n </span>\n <span class=\"description\" part=\"description\" ?hidden=\"${() => !slots.has('description').value}\">\n <slot name=\"description\"></slot>\n </span>\n </span>\n `;\n\n return html`\n <li class=\"step\" role=\"listitem\">\n <span class=\"connector connector-leading\" part=\"connector\" aria-hidden=\"true\"></span>\n <span class=\"connector connector-trailing\" part=\"connector\" aria-hidden=\"true\"></span>\n ${() =>\n isNavigable()\n ? html`\n <button\n type=\"button\"\n class=\"control\"\n part=\"control\"\n aria-current=\"${() => (isCurrent() ? 'step' : null)}\"\n aria-disabled=\"${isDisabled}\"\n tabindex=\"${() => (isCurrent() ? '0' : '-1')}\"\n @click=\"${handleClick}\">\n ${indicatorTemplate()}${contentTemplate()}\n </button>\n `\n : html`\n <div class=\"control\" part=\"control\" aria-current=\"${() => (isCurrent() ? 'step' : null)}\">\n ${indicatorTemplate()}${contentTemplate()}\n </div>\n `}\n </li>\n `;\n },\n styles: [colorThemeMixin, coarsePointerMixin, forcedColorsFocusMixin('button.control'), stepStyles],\n});\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"step.cjs","names":[],"sources":["../src/content/stepper/step.ts"],"sourcesContent":["import { bind, define, getHost, html, inject, prop, useSlots, watchEffect } from '@vielzeug/ore';\nimport { disablableBundle } from '../../shared';\nimport { coarsePointerMixin, colorThemeMixin, forcedColorsFocusMixin } from '../../styles';\nimport { COMPONENT_SIZES, type ComponentSize, THEME_COLORS, type ThemeColor } from '../../types';\nimport { isStepNavigable } from './_is-step-navigable';\nimport stepStyles from './step.css?inline';\nimport { STEPPER_CTX } from './stepper';\n\nexport { ICON_TAG } from '../icon/icon';\nexport type OreStepProps = {\n /**\n * Theme color. Inherited from the parent `ore-stepper` when nested inside one (overrides\n * this value); only takes effect on its own when `ore-step` is rendered standalone.\n */\n color?: ThemeColor;\n /** Disables this step: it cannot be navigated to and is skipped by keyboard navigation. */\n disabled?: boolean;\n /** Marks this step as failed/invalid. Overrides the completed/current indicator visuals. */\n error?: boolean;\n /**\n * Marks this step as optional. Renders a small \"(optional)\" hint next to the label.\n * Purely presentational: has no effect on navigation.\n */\n optional?: boolean;\n /** Orientation. Inherited from the parent `ore-stepper` when nested inside one. */\n orientation?: 'horizontal' | 'vertical';\n /** Component size. Inherited from the parent `ore-stepper` when nested inside one. */\n size?: ComponentSize;\n /** Unique identifier, matches `ore-stepper`'s `value` attribute. */\n value: string;\n};\n\n/**\n * A single step trigger. Must be placed as a direct child of `ore-stepper`, which provides\n * this step's current/completed/navigable/index/total state via context: those are derived,\n * read-only attributes on this element, not settable props.\n *\n * @element ore-step\n *\n * @attr {string} value - Unique identifier, matches the parent ore-stepper's `value` attribute\n * @attr {boolean} disabled - Prevents navigation to this step\n * @attr {boolean} error - Marks the step as failed/invalid\n * @attr {boolean} optional - Renders an \"(optional)\" hint next to the label\n * @attr {boolean} current - Read-only. Derived from position relative to the parent ore-stepper's `value`.\n * @attr {boolean} completed - Read-only. Derived from position relative to the parent ore-stepper's `value`.\n * @attr {boolean} navigable - Read-only. Derived from the parent ore-stepper's `clickable`/`linear`/`disabled`.\n * @attr {number} index - Read-only. This step's 1-based position among its siblings.\n * @attr {number} total - Read-only. Total sibling step count.\n * @attr {string} color - Inherited from ore-stepper: 'primary' | 'secondary' | 'info' | 'success' | 'warning' | 'error'\n * @attr {string} size - Inherited from ore-stepper: 'sm' | 'md' | 'lg'\n * @attr {string} orientation - Inherited from ore-stepper: 'horizontal' | 'vertical'\n *\n * @slot - Step label\n * @slot description - Optional supporting text shown below the label\n * @slot icon - Custom icon replacing the step number/check/error indicator\n *\n * @part control - Clickable (or static) root element for the step\n * @part indicator - Circular indicator holding the number/icon\n * @part content - Wrapper around the label and description\n * @part label - Step label element\n * @part description - Step description element\n * @part connector - Connector line segments (leading and trailing halves) either side of this step's indicator\n *\n * @example\n * ```html\n * <ore-step value=\"details\">Account details</ore-step>\n * <ore-step value=\"review\" disabled>Review</ore-step>\n * ```\n */\nexport const STEP_TAG = 'ore-step' as const;\ndefine<OreStepProps>(STEP_TAG, {\n props: {\n ...disablableBundle,\n color: prop.oneOf(THEME_COLORS),\n error: prop.bool(false),\n optional: prop.bool(false),\n orientation: prop.oneOf(['horizontal', 'vertical'] as const, 'horizontal'),\n size: prop.oneOf(COMPONENT_SIZES),\n value: prop.string(''),\n },\n setup(props) {\n const el = getHost();\n const slots = useSlots();\n const stepperCtx = inject(STEPPER_CTX);\n\n // ────────────────────────────────────────────────────────────────\n // State derived from the parent ore-stepper's context: see stepper.ts's\n // module doc comment for why this replaced parent-side attribute fan-out.\n // ────────────────────────────────────────────────────────────────\n\n // Plain functions, not `computed()`: every one of these ultimately reads\n // `stepperCtx.stepValues`/`stepperCtx.currentValue`, which are themselves `computed()`s\n // owned by the parent `ore-stepper`. Wrapping a *child* `computed()` around a *parent*\n // `computed()` (a computed-to-computed dependency crossing a `provide()`/`inject()`\n // boundary) is exactly the shape that surfaced two related bugs: a step's `completed`/\n // `current` attributes going permanently stale after a few rapid selections, and: worse :\n // a step's entire clickable/static control silently failing to render at all when its\n // `ore-step` tag upgrades before its siblings exist in the light DOM yet (true whenever\n // `ore-step`/`ore-stepper` are already `customElements.define()`d before this markup is\n // parsed, e.g. every sandboxed live-preview iframe). Reading straight through to the\n // parent's computeds on every call: no intermediate computed layer of our own to go\n // stale: made both disappear. Cheap enough to not need memoizing (a couple of `indexOf`/\n // comparisons over an already-memoized parent computed).\n const stepIndex = (): number => (stepperCtx ? stepperCtx.stepValues.value.indexOf(props.value.value) : -1);\n const totalSteps = (): number => stepperCtx?.stepValues.value.length ?? 0;\n const currentIndex = (): number =>\n stepperCtx ? stepperCtx.stepValues.value.indexOf(stepperCtx.currentValue.value ?? '') : -1;\n // 1-based, always-sane values for on-screen text (the step number badge, the sr-only\n // \"Step X of Y\" label): falls back to \"1 of 1\" when rendered standalone with no parent\n // `ore-stepper` to derive a real position from. Kept separate from the `index`/`total`\n // *attributes* below, which correctly reflect nothing at all in that same standalone case.\n const displayIndex = (): number => {\n const index = stepIndex();\n\n return index >= 0 ? index + 1 : 1;\n };\n const displayTotal = (): number => totalSteps() || 1;\n\n const isCurrent = (): boolean => {\n const index = stepIndex();\n const current = currentIndex();\n\n return index >= 0 && index === current;\n };\n // Purely positional: intentionally NOT gated on `props.error.value`. This also drives the\n // `completed` *attribute* below, which `step.css` uses to color both connector segments\n // either side of the indicator (`:host([completed]) .connector`); every *consumer* of this\n // (the icon choice, the sr-only state label) already checks `error` first and short-circuits\n // before it matters, so folding `!error` in here too would only end up suppressing\n // `[completed]` on an error step that's before the current one: breaking the connector\n // color chain right at that step instead of just swapping its icon.\n const isCompleted = (): boolean => {\n const index = stepIndex();\n const current = currentIndex();\n\n return index >= 0 && current >= 0 && index < current;\n };\n const isNavigable = (): boolean => {\n const index = stepIndex();\n const current = currentIndex();\n\n return (\n !!stepperCtx &&\n isStepNavigable({\n disabled: props.disabled.value === true,\n index,\n linear: stepperCtx.linear.value,\n stepperClickable: stepperCtx.clickable.value,\n stepperCurrentIndex: current,\n })\n );\n };\n const isDisabled = () => Boolean(props.disabled.value);\n\n // Purely derived, read-only state: no matching `prop.*` declaration, so `bind()` is the\n // sole writer and can safely reflect `undefined` (removes the attribute) when this step\n // isn't nested inside an `ore-stepper` at all.\n bind({\n attr: {\n completed: () => (isCompleted() ? true : undefined),\n current: () => (isCurrent() ? true : undefined),\n index: () => {\n const index = stepIndex();\n\n return index >= 0 ? String(index + 1) : undefined;\n },\n navigable: () => (isNavigable() ? true : undefined),\n total: () => (stepperCtx ? String(totalSteps()) : undefined),\n },\n });\n\n // `color`/`size`/`orientation` double as regular, independently-settable props (for a step\n // rendered standalone) *and* stepper-inherited values: mirrors ore-tab-item's handling of\n // its own `color`/`size`/`variant` inheritance from `ore-tabs`. Only forcibly overwrite the\n // attribute when a parent context actually exists, so the plain prop reflection is left\n // alone otherwise.\n if (stepperCtx) {\n watchEffect(() => {\n const color = stepperCtx.color.value;\n const size = stepperCtx.size.value;\n const orientation = stepperCtx.orientation.value;\n\n if (color !== undefined) el.setAttribute('color', color);\n\n if (size !== undefined) el.setAttribute('size', size);\n\n el.setAttribute('orientation', orientation);\n });\n }\n\n const stateLabel = (): string | undefined => {\n if (props.error.value) return 'error';\n\n if (isCompleted()) return 'completed';\n\n if (isCurrent()) return 'current step';\n\n return undefined;\n };\n\n const positionLabel = () => `Step ${displayIndex()} of ${displayTotal()}`;\n const srLabel = () => {\n const state = stateLabel();\n\n return state ? `${positionLabel()}, ${state}` : positionLabel();\n };\n\n const handleClick = (event: MouseEvent) => {\n event.stopPropagation();\n\n if (!isNavigable()) {\n event.preventDefault();\n\n return;\n }\n\n el.dispatchEvent(new CustomEvent('click', { bubbles: true, detail: { value: props.value.value } }));\n };\n\n const indicatorTemplate = () => html`\n <span class=\"indicator\" part=\"indicator\" aria-hidden=\"true\">\n <span class=\"icon-slot\" ?hidden=\"${() => !slots.has('icon').value}\"><slot name=\"icon\"></slot></span>\n ${() =>\n slots.has('icon').value\n ? ''\n : props.error.value\n ? html`\n <ore-icon name=\"x\" size=\"14\" stroke-width=\"3\"></ore-icon>\n `\n : isCompleted()\n ? html`\n <ore-icon name=\"check\" size=\"14\" stroke-width=\"3\"></ore-icon>\n `\n : html`\n <span class=\"number\">${displayIndex}</span>\n `}\n </span>\n `;\n\n const contentTemplate = () => html`\n <span class=\"content\" part=\"content\">\n <span class=\"sr-only\">${srLabel}</span>\n <span class=\"label\" part=\"label\">\n <span class=\"label-text\"><slot></slot></span>\n ${() =>\n props.optional.value\n ? html`\n <span class=\"optional-hint\">(optional)</span>\n `\n : ''}\n </span>\n <span class=\"description\" part=\"description\" ?hidden=\"${() => !slots.has('description').value}\">\n <slot name=\"description\"></slot>\n </span>\n </span>\n `;\n\n return html`\n <li class=\"step\" role=\"listitem\">\n <span class=\"connector connector-leading\" part=\"connector\" aria-hidden=\"true\"></span>\n <span class=\"connector connector-trailing\" part=\"connector\" aria-hidden=\"true\"></span>\n ${() =>\n isNavigable()\n ? html`\n <button\n type=\"button\"\n class=\"control\"\n part=\"control\"\n aria-current=\"${() => (isCurrent() ? 'step' : null)}\"\n aria-disabled=\"${isDisabled}\"\n tabindex=\"${() => (isCurrent() ? '0' : '-1')}\"\n @click=\"${handleClick}\">\n ${indicatorTemplate()}${contentTemplate()}\n </button>\n `\n : html`\n <div class=\"control\" part=\"control\" aria-current=\"${() => (isCurrent() ? 'step' : null)}\">\n ${indicatorTemplate()}${contentTemplate()}\n </div>\n `}\n </li>\n `;\n },\n styles: [colorThemeMixin, coarsePointerMixin, forcedColorsFocusMixin('button.control'), stepStyles],\n});\n"],"mappings":"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"}
|
package/dist/step.js
CHANGED
|
@@ -1,20 +1,20 @@
|
|
|
1
|
-
import{coarsePointerMixin as e}from"./styles/mixins/accessibility.css.js";import{colorThemeMixin as t,forcedColorsFocusMixin as n}from"./styles/mixins/theme.css.js";import{
|
|
1
|
+
import{coarsePointerMixin as e}from"./styles/mixins/accessibility.css.js";import{colorThemeMixin as t,forcedColorsFocusMixin as n}from"./styles/mixins/theme.css.js";import{COMPONENT_SIZES as r,THEME_COLORS as i}from"./shared/types.js";import{disablableBundle as a}from"./shared/prop-bundles.js";import{ICON_TAG as o}from"./icon.js";import{isStepNavigable as s}from"./content/stepper/_is-step-navigable.js";import c from"./content/stepper/step.css.js";import{STEPPER_CTX as l}from"./stepper.js";import{bind as u,define as d,getHost as f,html as p,inject as m,prop as h,useSlots as g,watchEffect as _}from"@vielzeug/ore";var v=`ore-step`;d(v,{props:{...a,color:h.oneOf(i),error:h.bool(!1),optional:h.bool(!1),orientation:h.oneOf([`horizontal`,`vertical`],`horizontal`),size:h.oneOf(r),value:h.string(``)},setup(e){let t=f(),n=g(),r=m(l),stepIndex=()=>r?r.stepValues.value.indexOf(e.value.value):-1,totalSteps=()=>r?.stepValues.value.length??0,currentIndex=()=>r?r.stepValues.value.indexOf(r.currentValue.value??``):-1,displayIndex=()=>{let e=stepIndex();return e>=0?e+1:1},displayTotal=()=>totalSteps()||1,isCurrent=()=>{let e=stepIndex(),t=currentIndex();return e>=0&&e===t},isCompleted=()=>{let e=stepIndex(),t=currentIndex();return e>=0&&t>=0&&e<t},isNavigable=()=>{let t=stepIndex(),n=currentIndex();return!!r&&s({disabled:e.disabled.value===!0,index:t,linear:r.linear.value,stepperClickable:r.clickable.value,stepperCurrentIndex:n})},isDisabled=()=>!!e.disabled.value;u({attr:{completed:()=>isCompleted()?!0:void 0,current:()=>isCurrent()?!0:void 0,index:()=>{let e=stepIndex();return e>=0?String(e+1):void 0},navigable:()=>isNavigable()?!0:void 0,total:()=>r?String(totalSteps()):void 0}}),r&&_(()=>{let e=r.color.value,n=r.size.value,i=r.orientation.value;e!==void 0&&t.setAttribute(`color`,e),n!==void 0&&t.setAttribute(`size`,n),t.setAttribute(`orientation`,i)});let stateLabel=()=>{if(e.error.value)return`error`;if(isCompleted())return`completed`;if(isCurrent())return`current step`},positionLabel=()=>`Step ${displayIndex()} of ${displayTotal()}`,srLabel=()=>{let e=stateLabel();return e?`${positionLabel()}, ${e}`:positionLabel()},handleClick=n=>{if(n.stopPropagation(),!isNavigable()){n.preventDefault();return}t.dispatchEvent(new CustomEvent(`click`,{bubbles:!0,detail:{value:e.value.value}}))},indicatorTemplate=()=>p`
|
|
2
2
|
<span class="indicator" part="indicator" aria-hidden="true">
|
|
3
3
|
<span class="icon-slot" ?hidden="${()=>!n.has(`icon`).value}"><slot name="icon"></slot></span>
|
|
4
|
-
${()=>n.has(`icon`).value?``:e.error.value?
|
|
4
|
+
${()=>n.has(`icon`).value?``:e.error.value?p`
|
|
5
5
|
<ore-icon name="x" size="14" stroke-width="3"></ore-icon>
|
|
6
|
-
`:isCompleted()?
|
|
6
|
+
`:isCompleted()?p`
|
|
7
7
|
<ore-icon name="check" size="14" stroke-width="3"></ore-icon>
|
|
8
|
-
`:
|
|
8
|
+
`:p`
|
|
9
9
|
<span class="number">${displayIndex}</span>
|
|
10
10
|
`}
|
|
11
11
|
</span>
|
|
12
|
-
`,contentTemplate=()=>
|
|
12
|
+
`,contentTemplate=()=>p`
|
|
13
13
|
<span class="content" part="content">
|
|
14
14
|
<span class="sr-only">${srLabel}</span>
|
|
15
15
|
<span class="label" part="label">
|
|
16
16
|
<span class="label-text"><slot></slot></span>
|
|
17
|
-
${()=>e.optional.value?
|
|
17
|
+
${()=>e.optional.value?p`
|
|
18
18
|
<span class="optional-hint">(optional)</span>
|
|
19
19
|
`:``}
|
|
20
20
|
</span>
|
|
@@ -22,11 +22,11 @@ import{coarsePointerMixin as e}from"./styles/mixins/accessibility.css.js";import
|
|
|
22
22
|
<slot name="description"></slot>
|
|
23
23
|
</span>
|
|
24
24
|
</span>
|
|
25
|
-
`;return
|
|
25
|
+
`;return p`
|
|
26
26
|
<li class="step" role="listitem">
|
|
27
27
|
<span class="connector connector-leading" part="connector" aria-hidden="true"></span>
|
|
28
28
|
<span class="connector connector-trailing" part="connector" aria-hidden="true"></span>
|
|
29
|
-
${()=>isNavigable()?
|
|
29
|
+
${()=>isNavigable()?p`
|
|
30
30
|
<button
|
|
31
31
|
type="button"
|
|
32
32
|
class="control"
|
|
@@ -37,11 +37,11 @@ import{coarsePointerMixin as e}from"./styles/mixins/accessibility.css.js";import
|
|
|
37
37
|
@click="${handleClick}">
|
|
38
38
|
${indicatorTemplate()}${contentTemplate()}
|
|
39
39
|
</button>
|
|
40
|
-
`:
|
|
40
|
+
`:p`
|
|
41
41
|
<div class="control" part="control" aria-current="${()=>isCurrent()?`step`:null}">
|
|
42
42
|
${indicatorTemplate()}${contentTemplate()}
|
|
43
43
|
</div>
|
|
44
44
|
`}
|
|
45
45
|
</li>
|
|
46
|
-
`},styles:[t,e,n(`button.control`),
|
|
46
|
+
`},styles:[t,e,n(`button.control`),c]});export{o as ICON_TAG,v as STEP_TAG};
|
|
47
47
|
//# sourceMappingURL=step.js.map
|
package/dist/step.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"step.js","names":[],"sources":["../src/content/stepper/step.ts"],"sourcesContent":["import { bind, define, getHost, html, inject, prop, useSlots, watchEffect } from '@vielzeug/ore';\nimport { disablableBundle } from '../../shared';\nimport { coarsePointerMixin, colorThemeMixin, forcedColorsFocusMixin } from '../../styles';\nimport type { ComponentSize, ThemeColor } from '../../types';\nimport { isStepNavigable } from './_is-step-navigable';\nimport stepStyles from './step.css?inline';\nimport { STEPPER_CTX } from './stepper';\n\nexport { ICON_TAG } from '../icon/icon';\nexport type OreStepProps = {\n /**\n * Theme color. Inherited from the parent `ore-stepper` when nested inside one (overrides\n * this value); only takes effect on its own when `ore-step` is rendered standalone.\n */\n color?: ThemeColor;\n /** Disables this step: it cannot be navigated to and is skipped by keyboard navigation. */\n disabled?: boolean;\n /** Marks this step as failed/invalid. Overrides the completed/current indicator visuals. */\n error?: boolean;\n /**\n * Marks this step as optional. Renders a small \"(optional)\" hint next to the label.\n * Purely presentational: has no effect on navigation.\n */\n optional?: boolean;\n /** Orientation. Inherited from the parent `ore-stepper` when nested inside one. */\n orientation?: 'horizontal' | 'vertical';\n /** Component size. Inherited from the parent `ore-stepper` when nested inside one. */\n size?: ComponentSize;\n /** Unique identifier, matches `ore-stepper`'s `value` attribute. */\n value: string;\n};\n\n/**\n * A single step trigger. Must be placed as a direct child of `ore-stepper`, which provides\n * this step's current/completed/navigable/index/total state via context: those are derived,\n * read-only attributes on this element, not settable props.\n *\n * @element ore-step\n *\n * @attr {string} value - Unique identifier, matches the parent ore-stepper's `value` attribute\n * @attr {boolean} disabled - Prevents navigation to this step\n * @attr {boolean} error - Marks the step as failed/invalid\n * @attr {boolean} optional - Renders an \"(optional)\" hint next to the label\n * @attr {boolean} current - Read-only. Derived from position relative to the parent ore-stepper's `value`.\n * @attr {boolean} completed - Read-only. Derived from position relative to the parent ore-stepper's `value`.\n * @attr {boolean} navigable - Read-only. Derived from the parent ore-stepper's `clickable`/`linear`/`disabled`.\n * @attr {number} index - Read-only. This step's 1-based position among its siblings.\n * @attr {number} total - Read-only. Total sibling step count.\n * @attr {string} color - Inherited from ore-stepper: 'primary' | 'secondary' | 'info' | 'success' | 'warning' | 'error'\n * @attr {string} size - Inherited from ore-stepper: 'sm' | 'md' | 'lg'\n * @attr {string} orientation - Inherited from ore-stepper: 'horizontal' | 'vertical'\n *\n * @slot - Step label\n * @slot description - Optional supporting text shown below the label\n * @slot icon - Custom icon replacing the step number/check/error indicator\n *\n * @part control - Clickable (or static) root element for the step\n * @part indicator - Circular indicator holding the number/icon\n * @part content - Wrapper around the label and description\n * @part label - Step label element\n * @part description - Step description element\n * @part connector - Connector line segments (leading and trailing halves) either side of this step's indicator\n *\n * @example\n * ```html\n * <ore-step value=\"details\">Account details</ore-step>\n * <ore-step value=\"review\" disabled>Review</ore-step>\n * ```\n */\nexport const STEP_TAG = 'ore-step' as const;\ndefine<OreStepProps>(STEP_TAG, {\n props: {\n ...disablableBundle,\n color: prop.string<ThemeColor>(),\n error: prop.bool(false),\n optional: prop.bool(false),\n orientation: prop.oneOf(['horizontal', 'vertical'] as const, 'horizontal'),\n size: prop.string<ComponentSize>(),\n value: prop.string(''),\n },\n setup(props) {\n const el = getHost();\n const slots = useSlots();\n const stepperCtx = inject(STEPPER_CTX);\n\n // ────────────────────────────────────────────────────────────────\n // State derived from the parent ore-stepper's context: see stepper.ts's\n // module doc comment for why this replaced parent-side attribute fan-out.\n // ────────────────────────────────────────────────────────────────\n\n // Plain functions, not `computed()`: every one of these ultimately reads\n // `stepperCtx.stepValues`/`stepperCtx.currentValue`, which are themselves `computed()`s\n // owned by the parent `ore-stepper`. Wrapping a *child* `computed()` around a *parent*\n // `computed()` (a computed-to-computed dependency crossing a `provide()`/`inject()`\n // boundary) is exactly the shape that surfaced two related bugs: a step's `completed`/\n // `current` attributes going permanently stale after a few rapid selections, and: worse :\n // a step's entire clickable/static control silently failing to render at all when its\n // `ore-step` tag upgrades before its siblings exist in the light DOM yet (true whenever\n // `ore-step`/`ore-stepper` are already `customElements.define()`d before this markup is\n // parsed, e.g. every sandboxed live-preview iframe). Reading straight through to the\n // parent's computeds on every call: no intermediate computed layer of our own to go\n // stale: made both disappear. Cheap enough to not need memoizing (a couple of `indexOf`/\n // comparisons over an already-memoized parent computed).\n const stepIndex = (): number => (stepperCtx ? stepperCtx.stepValues.value.indexOf(props.value.value) : -1);\n const totalSteps = (): number => stepperCtx?.stepValues.value.length ?? 0;\n const currentIndex = (): number =>\n stepperCtx ? stepperCtx.stepValues.value.indexOf(stepperCtx.currentValue.value ?? '') : -1;\n // 1-based, always-sane values for on-screen text (the step number badge, the sr-only\n // \"Step X of Y\" label): falls back to \"1 of 1\" when rendered standalone with no parent\n // `ore-stepper` to derive a real position from. Kept separate from the `index`/`total`\n // *attributes* below, which correctly reflect nothing at all in that same standalone case.\n const displayIndex = (): number => {\n const index = stepIndex();\n\n return index >= 0 ? index + 1 : 1;\n };\n const displayTotal = (): number => totalSteps() || 1;\n\n const isCurrent = (): boolean => {\n const index = stepIndex();\n const current = currentIndex();\n\n return index >= 0 && index === current;\n };\n // Purely positional: intentionally NOT gated on `props.error.value`. This also drives the\n // `completed` *attribute* below, which `step.css` uses to color both connector segments\n // either side of the indicator (`:host([completed]) .connector`); every *consumer* of this\n // (the icon choice, the sr-only state label) already checks `error` first and short-circuits\n // before it matters, so folding `!error` in here too would only end up suppressing\n // `[completed]` on an error step that's before the current one: breaking the connector\n // color chain right at that step instead of just swapping its icon.\n const isCompleted = (): boolean => {\n const index = stepIndex();\n const current = currentIndex();\n\n return index >= 0 && current >= 0 && index < current;\n };\n const isNavigable = (): boolean => {\n const index = stepIndex();\n const current = currentIndex();\n\n return (\n !!stepperCtx &&\n isStepNavigable({\n disabled: props.disabled.value === true,\n index,\n linear: stepperCtx.linear.value,\n stepperClickable: stepperCtx.clickable.value,\n stepperCurrentIndex: current,\n })\n );\n };\n const isDisabled = () => Boolean(props.disabled.value);\n\n // Purely derived, read-only state: no matching `prop.*` declaration, so `bind()` is the\n // sole writer and can safely reflect `undefined` (removes the attribute) when this step\n // isn't nested inside an `ore-stepper` at all.\n bind({\n attr: {\n completed: () => (isCompleted() ? true : undefined),\n current: () => (isCurrent() ? true : undefined),\n index: () => {\n const index = stepIndex();\n\n return index >= 0 ? String(index + 1) : undefined;\n },\n navigable: () => (isNavigable() ? true : undefined),\n total: () => (stepperCtx ? String(totalSteps()) : undefined),\n },\n });\n\n // `color`/`size`/`orientation` double as regular, independently-settable props (for a step\n // rendered standalone) *and* stepper-inherited values: mirrors ore-tab-item's handling of\n // its own `color`/`size`/`variant` inheritance from `ore-tabs`. Only forcibly overwrite the\n // attribute when a parent context actually exists, so the plain prop reflection is left\n // alone otherwise.\n if (stepperCtx) {\n watchEffect(() => {\n const color = stepperCtx.color.value;\n const size = stepperCtx.size.value;\n const orientation = stepperCtx.orientation.value;\n\n if (color !== undefined) el.setAttribute('color', color);\n\n if (size !== undefined) el.setAttribute('size', size);\n\n el.setAttribute('orientation', orientation);\n });\n }\n\n const stateLabel = (): string | undefined => {\n if (props.error.value) return 'error';\n\n if (isCompleted()) return 'completed';\n\n if (isCurrent()) return 'current step';\n\n return undefined;\n };\n\n const positionLabel = () => `Step ${displayIndex()} of ${displayTotal()}`;\n const srLabel = () => {\n const state = stateLabel();\n\n return state ? `${positionLabel()}, ${state}` : positionLabel();\n };\n\n const handleClick = (event: MouseEvent) => {\n event.stopPropagation();\n\n if (!isNavigable()) {\n event.preventDefault();\n\n return;\n }\n\n el.dispatchEvent(new CustomEvent('click', { bubbles: true, detail: { value: props.value.value } }));\n };\n\n const indicatorTemplate = () => html`\n <span class=\"indicator\" part=\"indicator\" aria-hidden=\"true\">\n <span class=\"icon-slot\" ?hidden=\"${() => !slots.has('icon').value}\"><slot name=\"icon\"></slot></span>\n ${() =>\n slots.has('icon').value\n ? ''\n : props.error.value\n ? html`\n <ore-icon name=\"x\" size=\"14\" stroke-width=\"3\"></ore-icon>\n `\n : isCompleted()\n ? html`\n <ore-icon name=\"check\" size=\"14\" stroke-width=\"3\"></ore-icon>\n `\n : html`\n <span class=\"number\">${displayIndex}</span>\n `}\n </span>\n `;\n\n const contentTemplate = () => html`\n <span class=\"content\" part=\"content\">\n <span class=\"sr-only\">${srLabel}</span>\n <span class=\"label\" part=\"label\">\n <span class=\"label-text\"><slot></slot></span>\n ${() =>\n props.optional.value\n ? html`\n <span class=\"optional-hint\">(optional)</span>\n `\n : ''}\n </span>\n <span class=\"description\" part=\"description\" ?hidden=\"${() => !slots.has('description').value}\">\n <slot name=\"description\"></slot>\n </span>\n </span>\n `;\n\n return html`\n <li class=\"step\" role=\"listitem\">\n <span class=\"connector connector-leading\" part=\"connector\" aria-hidden=\"true\"></span>\n <span class=\"connector connector-trailing\" part=\"connector\" aria-hidden=\"true\"></span>\n ${() =>\n isNavigable()\n ? html`\n <button\n type=\"button\"\n class=\"control\"\n part=\"control\"\n aria-current=\"${() => (isCurrent() ? 'step' : null)}\"\n aria-disabled=\"${isDisabled}\"\n tabindex=\"${() => (isCurrent() ? '0' : '-1')}\"\n @click=\"${handleClick}\">\n ${indicatorTemplate()}${contentTemplate()}\n </button>\n `\n : html`\n <div class=\"control\" part=\"control\" aria-current=\"${() => (isCurrent() ? 'step' : null)}\">\n ${indicatorTemplate()}${contentTemplate()}\n </div>\n `}\n </li>\n `;\n },\n styles: [colorThemeMixin, coarsePointerMixin, forcedColorsFocusMixin('button.control'), stepStyles],\n});\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"step.js","names":[],"sources":["../src/content/stepper/step.ts"],"sourcesContent":["import { bind, define, getHost, html, inject, prop, useSlots, watchEffect } from '@vielzeug/ore';\nimport { disablableBundle } from '../../shared';\nimport { coarsePointerMixin, colorThemeMixin, forcedColorsFocusMixin } from '../../styles';\nimport { COMPONENT_SIZES, type ComponentSize, THEME_COLORS, type ThemeColor } from '../../types';\nimport { isStepNavigable } from './_is-step-navigable';\nimport stepStyles from './step.css?inline';\nimport { STEPPER_CTX } from './stepper';\n\nexport { ICON_TAG } from '../icon/icon';\nexport type OreStepProps = {\n /**\n * Theme color. Inherited from the parent `ore-stepper` when nested inside one (overrides\n * this value); only takes effect on its own when `ore-step` is rendered standalone.\n */\n color?: ThemeColor;\n /** Disables this step: it cannot be navigated to and is skipped by keyboard navigation. */\n disabled?: boolean;\n /** Marks this step as failed/invalid. Overrides the completed/current indicator visuals. */\n error?: boolean;\n /**\n * Marks this step as optional. Renders a small \"(optional)\" hint next to the label.\n * Purely presentational: has no effect on navigation.\n */\n optional?: boolean;\n /** Orientation. Inherited from the parent `ore-stepper` when nested inside one. */\n orientation?: 'horizontal' | 'vertical';\n /** Component size. Inherited from the parent `ore-stepper` when nested inside one. */\n size?: ComponentSize;\n /** Unique identifier, matches `ore-stepper`'s `value` attribute. */\n value: string;\n};\n\n/**\n * A single step trigger. Must be placed as a direct child of `ore-stepper`, which provides\n * this step's current/completed/navigable/index/total state via context: those are derived,\n * read-only attributes on this element, not settable props.\n *\n * @element ore-step\n *\n * @attr {string} value - Unique identifier, matches the parent ore-stepper's `value` attribute\n * @attr {boolean} disabled - Prevents navigation to this step\n * @attr {boolean} error - Marks the step as failed/invalid\n * @attr {boolean} optional - Renders an \"(optional)\" hint next to the label\n * @attr {boolean} current - Read-only. Derived from position relative to the parent ore-stepper's `value`.\n * @attr {boolean} completed - Read-only. Derived from position relative to the parent ore-stepper's `value`.\n * @attr {boolean} navigable - Read-only. Derived from the parent ore-stepper's `clickable`/`linear`/`disabled`.\n * @attr {number} index - Read-only. This step's 1-based position among its siblings.\n * @attr {number} total - Read-only. Total sibling step count.\n * @attr {string} color - Inherited from ore-stepper: 'primary' | 'secondary' | 'info' | 'success' | 'warning' | 'error'\n * @attr {string} size - Inherited from ore-stepper: 'sm' | 'md' | 'lg'\n * @attr {string} orientation - Inherited from ore-stepper: 'horizontal' | 'vertical'\n *\n * @slot - Step label\n * @slot description - Optional supporting text shown below the label\n * @slot icon - Custom icon replacing the step number/check/error indicator\n *\n * @part control - Clickable (or static) root element for the step\n * @part indicator - Circular indicator holding the number/icon\n * @part content - Wrapper around the label and description\n * @part label - Step label element\n * @part description - Step description element\n * @part connector - Connector line segments (leading and trailing halves) either side of this step's indicator\n *\n * @example\n * ```html\n * <ore-step value=\"details\">Account details</ore-step>\n * <ore-step value=\"review\" disabled>Review</ore-step>\n * ```\n */\nexport const STEP_TAG = 'ore-step' as const;\ndefine<OreStepProps>(STEP_TAG, {\n props: {\n ...disablableBundle,\n color: prop.oneOf(THEME_COLORS),\n error: prop.bool(false),\n optional: prop.bool(false),\n orientation: prop.oneOf(['horizontal', 'vertical'] as const, 'horizontal'),\n size: prop.oneOf(COMPONENT_SIZES),\n value: prop.string(''),\n },\n setup(props) {\n const el = getHost();\n const slots = useSlots();\n const stepperCtx = inject(STEPPER_CTX);\n\n // ────────────────────────────────────────────────────────────────\n // State derived from the parent ore-stepper's context: see stepper.ts's\n // module doc comment for why this replaced parent-side attribute fan-out.\n // ────────────────────────────────────────────────────────────────\n\n // Plain functions, not `computed()`: every one of these ultimately reads\n // `stepperCtx.stepValues`/`stepperCtx.currentValue`, which are themselves `computed()`s\n // owned by the parent `ore-stepper`. Wrapping a *child* `computed()` around a *parent*\n // `computed()` (a computed-to-computed dependency crossing a `provide()`/`inject()`\n // boundary) is exactly the shape that surfaced two related bugs: a step's `completed`/\n // `current` attributes going permanently stale after a few rapid selections, and: worse :\n // a step's entire clickable/static control silently failing to render at all when its\n // `ore-step` tag upgrades before its siblings exist in the light DOM yet (true whenever\n // `ore-step`/`ore-stepper` are already `customElements.define()`d before this markup is\n // parsed, e.g. every sandboxed live-preview iframe). Reading straight through to the\n // parent's computeds on every call: no intermediate computed layer of our own to go\n // stale: made both disappear. Cheap enough to not need memoizing (a couple of `indexOf`/\n // comparisons over an already-memoized parent computed).\n const stepIndex = (): number => (stepperCtx ? stepperCtx.stepValues.value.indexOf(props.value.value) : -1);\n const totalSteps = (): number => stepperCtx?.stepValues.value.length ?? 0;\n const currentIndex = (): number =>\n stepperCtx ? stepperCtx.stepValues.value.indexOf(stepperCtx.currentValue.value ?? '') : -1;\n // 1-based, always-sane values for on-screen text (the step number badge, the sr-only\n // \"Step X of Y\" label): falls back to \"1 of 1\" when rendered standalone with no parent\n // `ore-stepper` to derive a real position from. Kept separate from the `index`/`total`\n // *attributes* below, which correctly reflect nothing at all in that same standalone case.\n const displayIndex = (): number => {\n const index = stepIndex();\n\n return index >= 0 ? index + 1 : 1;\n };\n const displayTotal = (): number => totalSteps() || 1;\n\n const isCurrent = (): boolean => {\n const index = stepIndex();\n const current = currentIndex();\n\n return index >= 0 && index === current;\n };\n // Purely positional: intentionally NOT gated on `props.error.value`. This also drives the\n // `completed` *attribute* below, which `step.css` uses to color both connector segments\n // either side of the indicator (`:host([completed]) .connector`); every *consumer* of this\n // (the icon choice, the sr-only state label) already checks `error` first and short-circuits\n // before it matters, so folding `!error` in here too would only end up suppressing\n // `[completed]` on an error step that's before the current one: breaking the connector\n // color chain right at that step instead of just swapping its icon.\n const isCompleted = (): boolean => {\n const index = stepIndex();\n const current = currentIndex();\n\n return index >= 0 && current >= 0 && index < current;\n };\n const isNavigable = (): boolean => {\n const index = stepIndex();\n const current = currentIndex();\n\n return (\n !!stepperCtx &&\n isStepNavigable({\n disabled: props.disabled.value === true,\n index,\n linear: stepperCtx.linear.value,\n stepperClickable: stepperCtx.clickable.value,\n stepperCurrentIndex: current,\n })\n );\n };\n const isDisabled = () => Boolean(props.disabled.value);\n\n // Purely derived, read-only state: no matching `prop.*` declaration, so `bind()` is the\n // sole writer and can safely reflect `undefined` (removes the attribute) when this step\n // isn't nested inside an `ore-stepper` at all.\n bind({\n attr: {\n completed: () => (isCompleted() ? true : undefined),\n current: () => (isCurrent() ? true : undefined),\n index: () => {\n const index = stepIndex();\n\n return index >= 0 ? String(index + 1) : undefined;\n },\n navigable: () => (isNavigable() ? true : undefined),\n total: () => (stepperCtx ? String(totalSteps()) : undefined),\n },\n });\n\n // `color`/`size`/`orientation` double as regular, independently-settable props (for a step\n // rendered standalone) *and* stepper-inherited values: mirrors ore-tab-item's handling of\n // its own `color`/`size`/`variant` inheritance from `ore-tabs`. Only forcibly overwrite the\n // attribute when a parent context actually exists, so the plain prop reflection is left\n // alone otherwise.\n if (stepperCtx) {\n watchEffect(() => {\n const color = stepperCtx.color.value;\n const size = stepperCtx.size.value;\n const orientation = stepperCtx.orientation.value;\n\n if (color !== undefined) el.setAttribute('color', color);\n\n if (size !== undefined) el.setAttribute('size', size);\n\n el.setAttribute('orientation', orientation);\n });\n }\n\n const stateLabel = (): string | undefined => {\n if (props.error.value) return 'error';\n\n if (isCompleted()) return 'completed';\n\n if (isCurrent()) return 'current step';\n\n return undefined;\n };\n\n const positionLabel = () => `Step ${displayIndex()} of ${displayTotal()}`;\n const srLabel = () => {\n const state = stateLabel();\n\n return state ? `${positionLabel()}, ${state}` : positionLabel();\n };\n\n const handleClick = (event: MouseEvent) => {\n event.stopPropagation();\n\n if (!isNavigable()) {\n event.preventDefault();\n\n return;\n }\n\n el.dispatchEvent(new CustomEvent('click', { bubbles: true, detail: { value: props.value.value } }));\n };\n\n const indicatorTemplate = () => html`\n <span class=\"indicator\" part=\"indicator\" aria-hidden=\"true\">\n <span class=\"icon-slot\" ?hidden=\"${() => !slots.has('icon').value}\"><slot name=\"icon\"></slot></span>\n ${() =>\n slots.has('icon').value\n ? ''\n : props.error.value\n ? html`\n <ore-icon name=\"x\" size=\"14\" stroke-width=\"3\"></ore-icon>\n `\n : isCompleted()\n ? html`\n <ore-icon name=\"check\" size=\"14\" stroke-width=\"3\"></ore-icon>\n `\n : html`\n <span class=\"number\">${displayIndex}</span>\n `}\n </span>\n `;\n\n const contentTemplate = () => html`\n <span class=\"content\" part=\"content\">\n <span class=\"sr-only\">${srLabel}</span>\n <span class=\"label\" part=\"label\">\n <span class=\"label-text\"><slot></slot></span>\n ${() =>\n props.optional.value\n ? html`\n <span class=\"optional-hint\">(optional)</span>\n `\n : ''}\n </span>\n <span class=\"description\" part=\"description\" ?hidden=\"${() => !slots.has('description').value}\">\n <slot name=\"description\"></slot>\n </span>\n </span>\n `;\n\n return html`\n <li class=\"step\" role=\"listitem\">\n <span class=\"connector connector-leading\" part=\"connector\" aria-hidden=\"true\"></span>\n <span class=\"connector connector-trailing\" part=\"connector\" aria-hidden=\"true\"></span>\n ${() =>\n isNavigable()\n ? html`\n <button\n type=\"button\"\n class=\"control\"\n part=\"control\"\n aria-current=\"${() => (isCurrent() ? 'step' : null)}\"\n aria-disabled=\"${isDisabled}\"\n tabindex=\"${() => (isCurrent() ? '0' : '-1')}\"\n @click=\"${handleClick}\">\n ${indicatorTemplate()}${contentTemplate()}\n </button>\n `\n : html`\n <div class=\"control\" part=\"control\" aria-current=\"${() => (isCurrent() ? 'step' : null)}\">\n ${indicatorTemplate()}${contentTemplate()}\n </div>\n `}\n </li>\n `;\n },\n styles: [colorThemeMixin, coarsePointerMixin, forcedColorsFocusMixin('button.control'), stepStyles],\n});\n"],"mappings":"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"}
|
package/dist/tab-item.cjs
CHANGED
|
@@ -1,17 +1,17 @@
|
|
|
1
|
-
Object.defineProperty(exports,Symbol.toStringTag,{value:`Module`});const e=require("./styles/mixins/accessibility.css.cjs"),t=require("./styles/mixins/theme.css.cjs"),n=require("./core/aria-reflection.cjs"),r=require("./shared/prop-bundles.cjs"),
|
|
1
|
+
Object.defineProperty(exports,Symbol.toStringTag,{value:`Module`});const e=require("./styles/mixins/accessibility.css.cjs"),t=require("./styles/mixins/theme.css.cjs"),n=require("./core/aria-reflection.cjs"),r=require("./shared/types.cjs"),i=require("./shared/prop-bundles.cjs"),a=require("./tabs.cjs"),o=require("./disclosure/tab-item/tab-item.css.cjs");let s=require("@vielzeug/ripple"),c=require("@vielzeug/ore");var l=`ore-tab-item`;(0,c.define)(l,{props:{...i.disablableBundle,active:c.prop.bool(!1),color:c.prop.oneOf(r.THEME_COLORS),density:c.prop.oneOf([`compact`,`default`],`default`),size:c.prop.oneOf(r.COMPONENT_SIZES),value:c.prop.string(``),variant:c.prop.oneOf(r.VISUAL_VARIANTS)},setup(e){let t=(0,c.getHost)(),r=c.watchEffect,i=(0,c.inject)(a.TABS_CTX);i&&r(()=>{let e=i.color.value,n=i.density.value,r=i.size.value,a=i.variant.value;e!==void 0&&t.setAttribute(`color`,e),t.setAttribute(`density`,n),r!==void 0&&t.setAttribute(`size`,r),a!==void 0&&t.setAttribute(`variant`,a)});let o=(0,s.computed)(()=>i?!!i.value.value&&i.value.value===e.value.value:e.active.value),isDisabled=()=>!!e.disabled.value;(0,c.bind)({attr:{active:()=>o.value?!0:void 0}});let handleClick=n=>{if(n.stopPropagation(),isDisabled()){n.preventDefault();return}t.dispatchEvent(new CustomEvent(`click`,{bubbles:!0,detail:{value:e.value.value}}))},tabId=()=>`tab-${e.value.value}`,l=(0,c.ref)();return(0,c.onMounted)(()=>{(0,c.watchEffect)(()=>{let r=l.value,i=e.value.value;if(!r)return;let a=((i?t.closest(`ore-tabs`):null)?.querySelector(`:scope > ore-tab-panel[value="${i}"]`))?.shadowRoot?.querySelector(`.panel`)??null;n.setAriaReflection(r,`ariaControlsElements`,a?[a]:[])})}),c.html`
|
|
2
2
|
<button
|
|
3
3
|
role="tab"
|
|
4
4
|
type="button"
|
|
5
5
|
part="tab"
|
|
6
6
|
ref="${l}"
|
|
7
7
|
id="${tabId}"
|
|
8
|
-
aria-selected="${
|
|
9
|
-
tabindex="${()=>
|
|
8
|
+
aria-selected="${o}"
|
|
9
|
+
tabindex="${()=>o.value?`0`:`-1`}"
|
|
10
10
|
aria-disabled="${isDisabled}"
|
|
11
11
|
@click="${handleClick}">
|
|
12
12
|
<slot name="prefix"></slot>
|
|
13
13
|
<slot></slot>
|
|
14
14
|
<slot name="suffix"></slot>
|
|
15
15
|
</button>
|
|
16
|
-
`},styles:[t.colorThemeMixin,t.forcedColorsFocusMixin(`button`),e.coarsePointerMixin,
|
|
16
|
+
`},styles:[t.colorThemeMixin,t.forcedColorsFocusMixin(`button`),e.coarsePointerMixin,o.default]}),exports.TAB_ITEM_TAG=l;
|
|
17
17
|
//# sourceMappingURL=tab-item.cjs.map
|
package/dist/tab-item.cjs.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"tab-item.cjs","names":[],"sources":["../src/disclosure/tab-item/tab-item.ts"],"sourcesContent":["import { bind, define, getHost, html, inject, onMounted, prop, ref, watchEffect } from '@vielzeug/ore';\nimport { computed } from '@vielzeug/ripple';\nimport { setAriaReflection } from '../../core';\nimport { disablableBundle } from '../../shared';\nimport { coarsePointerMixin, colorThemeMixin, forcedColorsFocusMixin } from '../../styles';\nimport type
|
|
1
|
+
{"version":3,"file":"tab-item.cjs","names":[],"sources":["../src/disclosure/tab-item/tab-item.ts"],"sourcesContent":["import { bind, define, getHost, html, inject, onMounted, prop, ref, watchEffect } from '@vielzeug/ore';\nimport { computed } from '@vielzeug/ripple';\nimport { setAriaReflection } from '../../core';\nimport { disablableBundle } from '../../shared';\nimport { coarsePointerMixin, colorThemeMixin, forcedColorsFocusMixin } from '../../styles';\nimport {\n COMPONENT_SIZES,\n type ComponentSize,\n THEME_COLORS,\n type ThemeColor,\n VISUAL_VARIANTS,\n type VisualVariant,\n} from '../../types';\nimport { TABS_CTX } from '../tabs/tabs';\nimport styles from './tab-item.css?inline';\n\nexport type OreTabItemProps = {\n /** Whether this tab is currently selected (set by ore-tabs) */\n active?: boolean;\n /** Theme color (inherited from ore-tabs) */\n color?: ThemeColor;\n /** Disable this tab */\n disabled?: boolean;\n /** Spatial density (inherited from ore-tabs) */\n density?: 'compact' | 'default';\n /** Size (inherited from ore-tabs) */\n size?: ComponentSize;\n /** Unique value identifier: must match a ore-tab-panel value */\n value: string;\n /** Visual variant (inherited from ore-tabs) */\n variant?: VisualVariant;\n};\n\n/**\n * Individual tab trigger. Must be placed in the `tabs` slot of `ore-tabs`.\n *\n * @element ore-tab-item\n *\n * @attr {string} value - Unique identifier, matches the corresponding ore-tab-panel value\n * @attr {boolean} active - Set by the parent ore-tabs when this tab is selected\n * @attr {boolean} disabled - Prevents selection\n * @attr {string} density - Inherited spatial density: 'default' | 'compact'\n * @attr {string} size - 'sm' | 'md' | 'lg'\n * @attr {string} variant - Inherited from ore-tabs: 'solid' | 'flat' | 'bordered' | 'ghost' | 'frost'\n * @attr {string} color - Inherited from ore-tabs: 'primary' | 'secondary' | 'info' | 'success' | 'warning' | 'error'\n *\n * @slot prefix - Icon or content before the label\n * @slot - Tab label\n * @slot suffix - Badge or count after the label\n *\n * @cssprop --tab-item-radius - Button border radius\n * @cssprop --tab-item-transition - Transition duration/easing\n * @cssprop --tab-item-padding - Button padding\n * @cssprop --tab-item-font-size - Button font size\n * @cssprop --tab-item-color - Default text color\n * @cssprop --tab-item-hover-bg - Background on hover\n * @cssprop --tab-item-active-bg - Background when active/selected\n * @cssprop --tab-item-active-color - Text color when active/selected\n * @cssprop --tab-item-active-shadow - Box shadow when active/selected\n * @part tab - Tab trigger element.\n * @example\n * ```html\n * <ore-tab-item slot=\"tabs\" value=\"overview\">Overview</ore-tab-item>\n * <ore-tab-item slot=\"tabs\" value=\"settings\" disabled>Settings</ore-tab-item>\n * ```\n */\nexport const TAB_ITEM_TAG = 'ore-tab-item' as const;\ndefine<OreTabItemProps>(TAB_ITEM_TAG, {\n props: {\n ...disablableBundle,\n active: prop.bool(false),\n color: prop.oneOf(THEME_COLORS),\n density: prop.oneOf(['compact', 'default'] as const, 'default'),\n size: prop.oneOf(COMPONENT_SIZES),\n value: prop.string(''),\n variant: prop.oneOf(VISUAL_VARIANTS),\n },\n setup(props) {\n const el = getHost();\n const watch = watchEffect;\n\n const tabsCtx = inject(TABS_CTX);\n\n if (tabsCtx) {\n watch(() => {\n const color = tabsCtx.color.value;\n const density = tabsCtx.density.value;\n const size = tabsCtx.size.value;\n const variant = tabsCtx.variant.value;\n\n if (color !== undefined) el.setAttribute('color', color);\n\n el.setAttribute('density', density);\n\n if (size !== undefined) el.setAttribute('size', size);\n\n if (variant !== undefined) el.setAttribute('variant', variant);\n });\n }\n\n const isActive = computed(() =>\n tabsCtx ? !!tabsCtx.value.value && tabsCtx.value.value === props.value.value : props.active.value,\n );\n const isDisabled = () => Boolean(props.disabled.value);\n\n bind({\n attr: {\n active: () => (isActive.value ? true : undefined),\n },\n });\n\n const handleClick = (event: MouseEvent) => {\n event.stopPropagation();\n\n if (isDisabled()) {\n event.preventDefault();\n\n return;\n }\n\n el.dispatchEvent(new CustomEvent('click', { bubbles: true, detail: { value: props.value.value } }));\n };\n\n const tabId = () => `tab-${props.value.value}`;\n const buttonRef = ref<HTMLButtonElement>();\n\n // `aria-controls` as a plain IDREF attribute cannot resolve across shadow-tree boundaries\n // (the matching `id` lives inside <ore-tab-panel>'s own shadow root): see\n // `setAriaReflection()`'s doc comment. Deferred to `onMounted()`: sibling custom elements\n // (including the peer `<ore-tab-panel>`) connect in tree order within the same synchronous\n // insertion, so a sibling's shadow content may not exist yet during this element's own\n // `setup()`: `onMounted()`'s microtask runs after the whole subtree has connected.\n onMounted(() => {\n watchEffect(() => {\n const button = buttonRef.value;\n const value = props.value.value;\n\n if (!button) return;\n\n const tabsEl = value ? el.closest('ore-tabs') : null;\n const panelEl = tabsEl?.querySelector<HTMLElement>(`:scope > ore-tab-panel[value=\"${value}\"]`);\n const panel = panelEl?.shadowRoot?.querySelector<HTMLElement>('.panel') ?? null;\n\n setAriaReflection(button, 'ariaControlsElements', panel ? [panel] : []);\n });\n });\n\n return html`\n <button\n role=\"tab\"\n type=\"button\"\n part=\"tab\"\n ref=\"${buttonRef}\"\n id=\"${tabId}\"\n aria-selected=\"${isActive}\"\n tabindex=\"${() => (isActive.value ? '0' : '-1')}\"\n aria-disabled=\"${isDisabled}\"\n @click=\"${handleClick}\">\n <slot name=\"prefix\"></slot>\n <slot></slot>\n <slot name=\"suffix\"></slot>\n </button>\n `;\n },\n styles: [colorThemeMixin, forcedColorsFocusMixin('button'), coarsePointerMixin, styles],\n});\n"],"mappings":"+ZAkEA,IAAa,EAAe,gBAC5B,EAAA,EAAA,OAAA,CAAwB,EAAc,CACpC,MAAO,CACL,GAAG,EAAA,iBACH,OAAQ,EAAA,KAAK,KAAK,EAAK,EACvB,MAAO,EAAA,KAAK,MAAM,EAAA,YAAY,EAC9B,QAAS,EAAA,KAAK,MAAM,CAAC,UAAW,SAAS,EAAY,SAAS,EAC9D,KAAM,EAAA,KAAK,MAAM,EAAA,eAAe,EAChC,MAAO,EAAA,KAAK,OAAO,EAAE,EACrB,QAAS,EAAA,KAAK,MAAM,EAAA,eAAe,CACrC,EACA,MAAM,EAAO,CACX,IAAM,GAAA,EAAK,EAAA,QAAA,CAAQ,EACb,EAAQ,EAAA,YAER,GAAA,EAAU,EAAA,OAAA,CAAO,EAAA,QAAQ,EAE3B,GACF,MAAY,CACV,IAAM,EAAQ,EAAQ,MAAM,MACtB,EAAU,EAAQ,QAAQ,MAC1B,EAAO,EAAQ,KAAK,MACpB,EAAU,EAAQ,QAAQ,MAE5B,IAAU,IAAA,IAAW,EAAG,aAAa,QAAS,CAAK,EAEvD,EAAG,aAAa,UAAW,CAAO,EAE9B,IAAS,IAAA,IAAW,EAAG,aAAa,OAAQ,CAAI,EAEhD,IAAY,IAAA,IAAW,EAAG,aAAa,UAAW,CAAO,CAC/D,CAAC,EAGH,IAAM,GAAA,EAAW,EAAA,SAAA,KACf,EAAU,CAAC,CAAC,EAAQ,MAAM,OAAS,EAAQ,MAAM,QAAU,EAAM,MAAM,MAAQ,EAAM,OAAO,KAC9F,EACM,eAAmB,EAAQ,EAAM,SAAS,OAEhD,EAAA,EAAA,KAAA,CAAK,CACH,KAAM,CACJ,WAAe,EAAS,MAAQ,GAAO,IAAA,EACzC,CACF,CAAC,EAED,IAAM,YAAe,GAAsB,CAGzC,GAFA,EAAM,gBAAgB,EAElB,WAAW,EAAG,CAChB,EAAM,eAAe,EAErB,MACF,CAEA,EAAG,cAAc,IAAI,YAAY,QAAS,CAAE,QAAS,GAAM,OAAQ,CAAE,MAAO,EAAM,MAAM,KAAM,CAAE,CAAC,CAAC,CACpG,EAEM,UAAc,OAAO,EAAM,MAAM,QACjC,GAAA,EAAY,EAAA,IAAA,CAAuB,EAuBzC,OAfA,EAAA,EAAA,UAAA,KAAgB,EACd,EAAA,EAAA,YAAA,KAAkB,CAChB,IAAM,EAAS,EAAU,MACnB,EAAQ,EAAM,MAAM,MAE1B,GAAI,CAAC,EAAQ,OAIb,IAAM,IAFS,EAAQ,EAAG,QAAQ,UAAU,EAAI,KAAA,EACxB,cAA2B,iCAAiC,EAAM,GAAG,EAAA,EACtE,YAAY,cAA2B,QAAQ,GAAK,KAE3E,EAAA,kBAAkB,EAAQ,uBAAwB,EAAQ,CAAC,CAAK,EAAI,CAAC,CAAC,CACxE,CAAC,CACH,CAAC,EAEM,EAAA,IAAI;;;;;eAKA,EAAU;cACX,MAAM;yBACK,EAAS;wBACP,EAAS,MAAQ,IAAM,KAAM;yBAC/B,WAAW;kBAClB,YAAY;;;;;KAM5B,EACA,OAAQ,CAAC,EAAA,gBAAiB,EAAA,uBAAuB,QAAQ,EAAG,EAAA,mBAAoB,EAAA,OAAM,CACxF,CAAC"}
|
package/dist/tab-item.js
CHANGED
|
@@ -1,17 +1,17 @@
|
|
|
1
|
-
import{coarsePointerMixin as e}from"./styles/mixins/accessibility.css.js";import{colorThemeMixin as t,forcedColorsFocusMixin as n}from"./styles/mixins/theme.css.js";import{setAriaReflection as r}from"./core/aria-reflection.js";import{
|
|
1
|
+
import{coarsePointerMixin as e}from"./styles/mixins/accessibility.css.js";import{colorThemeMixin as t,forcedColorsFocusMixin as n}from"./styles/mixins/theme.css.js";import{setAriaReflection as r}from"./core/aria-reflection.js";import{COMPONENT_SIZES as i,THEME_COLORS as a,VISUAL_VARIANTS as o}from"./shared/types.js";import{disablableBundle as s}from"./shared/prop-bundles.js";import{TABS_CTX as c}from"./tabs.js";import l from"./disclosure/tab-item/tab-item.css.js";import{computed as u}from"@vielzeug/ripple";import{bind as d,define as f,getHost as p,html as m,inject as h,onMounted as g,prop as _,ref as v,watchEffect as y}from"@vielzeug/ore";var b=`ore-tab-item`;f(b,{props:{...s,active:_.bool(!1),color:_.oneOf(a),density:_.oneOf([`compact`,`default`],`default`),size:_.oneOf(i),value:_.string(``),variant:_.oneOf(o)},setup(e){let t=p(),n=y,i=h(c);i&&n(()=>{let e=i.color.value,n=i.density.value,r=i.size.value,a=i.variant.value;e!==void 0&&t.setAttribute(`color`,e),t.setAttribute(`density`,n),r!==void 0&&t.setAttribute(`size`,r),a!==void 0&&t.setAttribute(`variant`,a)});let a=u(()=>i?!!i.value.value&&i.value.value===e.value.value:e.active.value),isDisabled=()=>!!e.disabled.value;d({attr:{active:()=>a.value?!0:void 0}});let handleClick=n=>{if(n.stopPropagation(),isDisabled()){n.preventDefault();return}t.dispatchEvent(new CustomEvent(`click`,{bubbles:!0,detail:{value:e.value.value}}))},tabId=()=>`tab-${e.value.value}`,o=v();return g(()=>{y(()=>{let n=o.value,i=e.value.value;if(!n)return;let a=((i?t.closest(`ore-tabs`):null)?.querySelector(`:scope > ore-tab-panel[value="${i}"]`))?.shadowRoot?.querySelector(`.panel`)??null;r(n,`ariaControlsElements`,a?[a]:[])})}),m`
|
|
2
2
|
<button
|
|
3
3
|
role="tab"
|
|
4
4
|
type="button"
|
|
5
5
|
part="tab"
|
|
6
|
-
ref="${
|
|
6
|
+
ref="${o}"
|
|
7
7
|
id="${tabId}"
|
|
8
|
-
aria-selected="${
|
|
9
|
-
tabindex="${()=>
|
|
8
|
+
aria-selected="${a}"
|
|
9
|
+
tabindex="${()=>a.value?`0`:`-1`}"
|
|
10
10
|
aria-disabled="${isDisabled}"
|
|
11
11
|
@click="${handleClick}">
|
|
12
12
|
<slot name="prefix"></slot>
|
|
13
13
|
<slot></slot>
|
|
14
14
|
<slot name="suffix"></slot>
|
|
15
15
|
</button>
|
|
16
|
-
`},styles:[t,n(`button`),e,
|
|
16
|
+
`},styles:[t,n(`button`),e,l]});export{b as TAB_ITEM_TAG};
|
|
17
17
|
//# sourceMappingURL=tab-item.js.map
|
package/dist/tab-item.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"tab-item.js","names":[],"sources":["../src/disclosure/tab-item/tab-item.ts"],"sourcesContent":["import { bind, define, getHost, html, inject, onMounted, prop, ref, watchEffect } from '@vielzeug/ore';\nimport { computed } from '@vielzeug/ripple';\nimport { setAriaReflection } from '../../core';\nimport { disablableBundle } from '../../shared';\nimport { coarsePointerMixin, colorThemeMixin, forcedColorsFocusMixin } from '../../styles';\nimport type
|
|
1
|
+
{"version":3,"file":"tab-item.js","names":[],"sources":["../src/disclosure/tab-item/tab-item.ts"],"sourcesContent":["import { bind, define, getHost, html, inject, onMounted, prop, ref, watchEffect } from '@vielzeug/ore';\nimport { computed } from '@vielzeug/ripple';\nimport { setAriaReflection } from '../../core';\nimport { disablableBundle } from '../../shared';\nimport { coarsePointerMixin, colorThemeMixin, forcedColorsFocusMixin } from '../../styles';\nimport {\n COMPONENT_SIZES,\n type ComponentSize,\n THEME_COLORS,\n type ThemeColor,\n VISUAL_VARIANTS,\n type VisualVariant,\n} from '../../types';\nimport { TABS_CTX } from '../tabs/tabs';\nimport styles from './tab-item.css?inline';\n\nexport type OreTabItemProps = {\n /** Whether this tab is currently selected (set by ore-tabs) */\n active?: boolean;\n /** Theme color (inherited from ore-tabs) */\n color?: ThemeColor;\n /** Disable this tab */\n disabled?: boolean;\n /** Spatial density (inherited from ore-tabs) */\n density?: 'compact' | 'default';\n /** Size (inherited from ore-tabs) */\n size?: ComponentSize;\n /** Unique value identifier: must match a ore-tab-panel value */\n value: string;\n /** Visual variant (inherited from ore-tabs) */\n variant?: VisualVariant;\n};\n\n/**\n * Individual tab trigger. Must be placed in the `tabs` slot of `ore-tabs`.\n *\n * @element ore-tab-item\n *\n * @attr {string} value - Unique identifier, matches the corresponding ore-tab-panel value\n * @attr {boolean} active - Set by the parent ore-tabs when this tab is selected\n * @attr {boolean} disabled - Prevents selection\n * @attr {string} density - Inherited spatial density: 'default' | 'compact'\n * @attr {string} size - 'sm' | 'md' | 'lg'\n * @attr {string} variant - Inherited from ore-tabs: 'solid' | 'flat' | 'bordered' | 'ghost' | 'frost'\n * @attr {string} color - Inherited from ore-tabs: 'primary' | 'secondary' | 'info' | 'success' | 'warning' | 'error'\n *\n * @slot prefix - Icon or content before the label\n * @slot - Tab label\n * @slot suffix - Badge or count after the label\n *\n * @cssprop --tab-item-radius - Button border radius\n * @cssprop --tab-item-transition - Transition duration/easing\n * @cssprop --tab-item-padding - Button padding\n * @cssprop --tab-item-font-size - Button font size\n * @cssprop --tab-item-color - Default text color\n * @cssprop --tab-item-hover-bg - Background on hover\n * @cssprop --tab-item-active-bg - Background when active/selected\n * @cssprop --tab-item-active-color - Text color when active/selected\n * @cssprop --tab-item-active-shadow - Box shadow when active/selected\n * @part tab - Tab trigger element.\n * @example\n * ```html\n * <ore-tab-item slot=\"tabs\" value=\"overview\">Overview</ore-tab-item>\n * <ore-tab-item slot=\"tabs\" value=\"settings\" disabled>Settings</ore-tab-item>\n * ```\n */\nexport const TAB_ITEM_TAG = 'ore-tab-item' as const;\ndefine<OreTabItemProps>(TAB_ITEM_TAG, {\n props: {\n ...disablableBundle,\n active: prop.bool(false),\n color: prop.oneOf(THEME_COLORS),\n density: prop.oneOf(['compact', 'default'] as const, 'default'),\n size: prop.oneOf(COMPONENT_SIZES),\n value: prop.string(''),\n variant: prop.oneOf(VISUAL_VARIANTS),\n },\n setup(props) {\n const el = getHost();\n const watch = watchEffect;\n\n const tabsCtx = inject(TABS_CTX);\n\n if (tabsCtx) {\n watch(() => {\n const color = tabsCtx.color.value;\n const density = tabsCtx.density.value;\n const size = tabsCtx.size.value;\n const variant = tabsCtx.variant.value;\n\n if (color !== undefined) el.setAttribute('color', color);\n\n el.setAttribute('density', density);\n\n if (size !== undefined) el.setAttribute('size', size);\n\n if (variant !== undefined) el.setAttribute('variant', variant);\n });\n }\n\n const isActive = computed(() =>\n tabsCtx ? !!tabsCtx.value.value && tabsCtx.value.value === props.value.value : props.active.value,\n );\n const isDisabled = () => Boolean(props.disabled.value);\n\n bind({\n attr: {\n active: () => (isActive.value ? true : undefined),\n },\n });\n\n const handleClick = (event: MouseEvent) => {\n event.stopPropagation();\n\n if (isDisabled()) {\n event.preventDefault();\n\n return;\n }\n\n el.dispatchEvent(new CustomEvent('click', { bubbles: true, detail: { value: props.value.value } }));\n };\n\n const tabId = () => `tab-${props.value.value}`;\n const buttonRef = ref<HTMLButtonElement>();\n\n // `aria-controls` as a plain IDREF attribute cannot resolve across shadow-tree boundaries\n // (the matching `id` lives inside <ore-tab-panel>'s own shadow root): see\n // `setAriaReflection()`'s doc comment. Deferred to `onMounted()`: sibling custom elements\n // (including the peer `<ore-tab-panel>`) connect in tree order within the same synchronous\n // insertion, so a sibling's shadow content may not exist yet during this element's own\n // `setup()`: `onMounted()`'s microtask runs after the whole subtree has connected.\n onMounted(() => {\n watchEffect(() => {\n const button = buttonRef.value;\n const value = props.value.value;\n\n if (!button) return;\n\n const tabsEl = value ? el.closest('ore-tabs') : null;\n const panelEl = tabsEl?.querySelector<HTMLElement>(`:scope > ore-tab-panel[value=\"${value}\"]`);\n const panel = panelEl?.shadowRoot?.querySelector<HTMLElement>('.panel') ?? null;\n\n setAriaReflection(button, 'ariaControlsElements', panel ? [panel] : []);\n });\n });\n\n return html`\n <button\n role=\"tab\"\n type=\"button\"\n part=\"tab\"\n ref=\"${buttonRef}\"\n id=\"${tabId}\"\n aria-selected=\"${isActive}\"\n tabindex=\"${() => (isActive.value ? '0' : '-1')}\"\n aria-disabled=\"${isDisabled}\"\n @click=\"${handleClick}\">\n <slot name=\"prefix\"></slot>\n <slot></slot>\n <slot name=\"suffix\"></slot>\n </button>\n `;\n },\n styles: [colorThemeMixin, forcedColorsFocusMixin('button'), coarsePointerMixin, styles],\n});\n"],"mappings":"uoBAkEA,IAAa,EAAe,eAC5B,EAAwB,EAAc,CACpC,MAAO,CACL,GAAG,EACH,OAAQ,EAAK,KAAK,EAAK,EACvB,MAAO,EAAK,MAAM,CAAY,EAC9B,QAAS,EAAK,MAAM,CAAC,UAAW,SAAS,EAAY,SAAS,EAC9D,KAAM,EAAK,MAAM,CAAe,EAChC,MAAO,EAAK,OAAO,EAAE,EACrB,QAAS,EAAK,MAAM,CAAe,CACrC,EACA,MAAM,EAAO,CACX,IAAM,EAAK,EAAQ,EACb,EAAQ,EAER,EAAU,EAAO,CAAQ,EAE3B,GACF,MAAY,CACV,IAAM,EAAQ,EAAQ,MAAM,MACtB,EAAU,EAAQ,QAAQ,MAC1B,EAAO,EAAQ,KAAK,MACpB,EAAU,EAAQ,QAAQ,MAE5B,IAAU,IAAA,IAAW,EAAG,aAAa,QAAS,CAAK,EAEvD,EAAG,aAAa,UAAW,CAAO,EAE9B,IAAS,IAAA,IAAW,EAAG,aAAa,OAAQ,CAAI,EAEhD,IAAY,IAAA,IAAW,EAAG,aAAa,UAAW,CAAO,CAC/D,CAAC,EAGH,IAAM,EAAW,MACf,EAAU,CAAC,CAAC,EAAQ,MAAM,OAAS,EAAQ,MAAM,QAAU,EAAM,MAAM,MAAQ,EAAM,OAAO,KAC9F,EACM,eAAmB,EAAQ,EAAM,SAAS,MAEhD,EAAK,CACH,KAAM,CACJ,WAAe,EAAS,MAAQ,GAAO,IAAA,EACzC,CACF,CAAC,EAED,IAAM,YAAe,GAAsB,CAGzC,GAFA,EAAM,gBAAgB,EAElB,WAAW,EAAG,CAChB,EAAM,eAAe,EAErB,MACF,CAEA,EAAG,cAAc,IAAI,YAAY,QAAS,CAAE,QAAS,GAAM,OAAQ,CAAE,MAAO,EAAM,MAAM,KAAM,CAAE,CAAC,CAAC,CACpG,EAEM,UAAc,OAAO,EAAM,MAAM,QACjC,EAAY,EAAuB,EAuBzC,OAfA,MAAgB,CACd,MAAkB,CAChB,IAAM,EAAS,EAAU,MACnB,EAAQ,EAAM,MAAM,MAE1B,GAAI,CAAC,EAAQ,OAIb,IAAM,IAFS,EAAQ,EAAG,QAAQ,UAAU,EAAI,KAAA,EACxB,cAA2B,iCAAiC,EAAM,GAAG,EAAA,EACtE,YAAY,cAA2B,QAAQ,GAAK,KAE3E,EAAkB,EAAQ,uBAAwB,EAAQ,CAAC,CAAK,EAAI,CAAC,CAAC,CACxE,CAAC,CACH,CAAC,EAEM,CAAI;;;;;eAKA,EAAU;cACX,MAAM;yBACK,EAAS;wBACP,EAAS,MAAQ,IAAM,KAAM;yBAC/B,WAAW;kBAClB,YAAY;;;;;KAM5B,EACA,OAAQ,CAAC,EAAiB,EAAuB,QAAQ,EAAG,EAAoB,CAAM,CACxF,CAAC"}
|
package/dist/table.cjs
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
Object.defineProperty(exports,Symbol.toStringTag,{value:`Module`});const e=require("./styles/mixins/accessibility.css.cjs"),t=require("./styles/mixins/table-base.css.cjs"),n=require("./content/table/table.css.cjs");let
|
|
1
|
+
Object.defineProperty(exports,Symbol.toStringTag,{value:`Module`});const e=require("./styles/mixins/accessibility.css.cjs"),t=require("./styles/mixins/table-base.css.cjs"),n=require("./shared/types.cjs"),r=require("./content/table/table.css.cjs");let i=require("@vielzeug/ore");customElements.get(`ore-tr`)||customElements.define(`ore-tr`,class extends HTMLElement{}),customElements.get(`ore-th`)||customElements.define(`ore-th`,class extends HTMLElement{}),customElements.get(`ore-td`)||customElements.define(`ore-td`,class extends HTMLElement{});var a=[`colspan`,`rowspan`,`headers`,`abbr`];function syncCell(e,t,n){if(e.childElementCount>0){let n=e.innerHTML;if(t.getAttribute(`data-src-html`)===n)return;t.setAttribute(`data-src-html`,n),t.textContent=``;for(let n of e.childNodes)t.appendChild(n.cloneNode(!0))}else{let n=e.textContent??``;t.textContent!==n&&(t.textContent=n)}for(let n of a){let r=e.getAttribute(n);r===null?t.removeAttribute(n):t.setAttribute(n,r)}let r=e.getAttribute(`scope`);r===null?n?t.scope=n:t.removeAttribute(`scope`):t.setAttribute(`scope`,r)}function buildTable(e,t,n,r){let i=new WeakMap;t.textContent=``,n.textContent=``,r.textContent=``;for(let a of e.children){if(a.localName!==`ore-tr`)continue;let e=a.hasAttribute(`head`)?t:a.hasAttribute(`foot`)?r:n,o=document.createElement(`tr`);for(let r of a.children){if(r.localName!==`ore-th`&&r.localName!==`ore-td`)continue;let a=r.localName===`ore-th`,s=document.createElement(a?`th`:`td`),c=a?e===t?`col`:`row`:void 0;s.setAttribute(`part`,e===n?`cell`:`header-cell`),s.removeAttribute(`data-src-html`),syncCell(r,s,c),i.set(r,{inferredScope:c,native:s}),o.appendChild(s)}e.appendChild(o)}return i}var o=`ore-table`;(0,i.define)(o,{props:{bordered:i.prop.bool(!1),caption:i.prop.string(),density:i.prop.oneOf(n.DENSITY_LEVELS),fullwidth:i.prop.bool(!1),loading:i.prop.bool(!1),sticky:i.prop.bool(!1),striped:i.prop.bool(!1)},setup(e){let t=(0,i.getHost)(),n=i.watchEffect;return(0,i.bind)({attr:{"aria-busy":e.loading,"aria-label":e.caption}}),(0,i.onMounted)(()=>{let r=t.shadowRoot?.querySelector(`.scroll-container`),i=document.createElement(`table`),o=document.createElement(`caption`),s=document.createElement(`thead`),c=document.createElement(`tbody`),l=document.createElement(`tfoot`);r.setAttribute(`part`,`scroll`),i.setAttribute(`part`,`table`),s.setAttribute(`part`,`head`),c.setAttribute(`part`,`body`),l.setAttribute(`part`,`foot`),i.append(o,s,c,l),r.appendChild(i),n(()=>{let t=e.caption.value??``;o.textContent=t,o.hidden=t===``});let u=buildTable(t,s,c,l),d=new MutationObserver(e=>{for(let t of e){let e=(t.target instanceof Element?t.target:t.target.parentElement)?.closest(`ore-th, ore-td`);if(e){let t=u.get(e);t&&syncCell(e,t.native,t.inferredScope)}}});d.observe(t,{attributeFilter:[...a,`scope`],attributes:!0,characterData:!0,childList:!0,subtree:!0});let f=new MutationObserver(()=>{u=buildTable(t,s,c,l)});return f.observe(t,{childList:!0}),()=>{f.disconnect(),d.disconnect()}}),i.html`
|
|
2
2
|
<div class="scroll-container"></div>
|
|
3
|
-
`},styles:[e.reducedMotionMixin,t.tableBaseMixin(`table`),
|
|
3
|
+
`},styles:[e.reducedMotionMixin,t.tableBaseMixin(`table`),r.default]}),exports.TABLE_TAG=o;
|
|
4
4
|
//# sourceMappingURL=table.cjs.map
|
package/dist/table.cjs.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"table.cjs","names":[],"sources":["../src/content/table/table.ts"],"sourcesContent":["import { bind, define, getHost, html, onMounted, prop, watchEffect } from '@vielzeug/ore';\n\nimport { reducedMotionMixin, tableBaseMixin } from '../../styles';\nimport componentStyles from './table.css?inline';\n\n/* ── Types ───────────────────────────────────────────────────────────────── */\n\n/** Table component properties */\nexport type OreTableProps = {\n /** Adds a thicker outer border */\n bordered?: boolean;\n /** Visible caption text: also used as the accessible table label via `aria-label` */\n caption?: string;\n /** Cell density: `'compact'` | `'cozy'` (default) | `'comfortable'` */\n density?: 'compact' | 'cozy' | 'comfortable';\n /** Expands the table to 100% of its container width */\n fullwidth?: boolean;\n /** Applies a busy/disabled state with reduced opacity */\n loading?: boolean;\n /** Enables sticky column headers with a vertical scroll container */\n sticky?: boolean;\n /** Alternating row stripe backgrounds */\n striped?: boolean;\n};\n\n/* ── Child element markers ───────────────────────────────────────────────── */\n// ore-tr, ore-th, ore-td are lightweight light-DOM markers.\n// ore-table reads them and constructs a fully-native shadow <table> so that\n// browser features that require real table elements (colspan/rowspan,\n// position:sticky on <thead>, table layout algorithm) all work correctly.\n// Attributes on ore-th/ore-td are mirrored to the generated native cells.\n\n/**\n * Light-DOM row marker consumed by `<ore-table>`.\n *\n * @element ore-tr\n * @attr {boolean} head - Places the row in the generated `<thead>` section\n * @attr {boolean} foot - Places the row in the generated `<tfoot>` section\n *\n * @example\n * ```html\n * <ore-table>\n * <ore-tr head><ore-th>Name</ore-th><ore-th>Role</ore-th></ore-tr>\n * <ore-tr><ore-td>Alice</ore-td><ore-td>Admin</ore-td></ore-tr>\n * </ore-table>\n * ```\n */\nif (!customElements.get('ore-tr')) customElements.define('ore-tr', class extends HTMLElement {});\n\n/**\n * Light-DOM header cell marker consumed by `<ore-table>`.\n *\n * @element ore-th\n * @attr {number} colspan - Mirrors to native `<th colspan>`\n * @attr {number} rowspan - Mirrors to native `<th rowspan>`\n * @attr {string} scope - Mirrors to native `<th scope>`: 'col' | 'row' | 'colgroup' | 'rowgroup'\n * @attr {string} headers - Mirrors to native `<th headers>`\n *\n * @example\n * ```html\n * <ore-tr head>\n * <ore-th scope=\"col\">Name</ore-th>\n * <ore-th scope=\"col\" colspan=\"2\">Address</ore-th>\n * </ore-tr>\n * ```\n */\nif (!customElements.get('ore-th')) customElements.define('ore-th', class extends HTMLElement {});\n\n/**\n * Light-DOM data cell marker consumed by `<ore-table>`.\n *\n * @element ore-td\n * @attr {number} colspan - Mirrors to native `<td colspan>`\n * @attr {number} rowspan - Mirrors to native `<td rowspan>`\n * @attr {string} headers - Mirrors to native `<td headers>`\n *\n * @example\n * ```html\n * <ore-tr>\n * <ore-td>Alice</ore-td>\n * <ore-td colspan=\"2\">123 Main St, Springfield</ore-td>\n * </ore-tr>\n * ```\n */\nif (!customElements.get('ore-td')) customElements.define('ore-td', class extends HTMLElement {});\n\n/* ── Proxy/mirror helpers ────────────────────────────────────────────────── */\n\n// Attributes forwarded from ore-th/ore-td to the generated native cell.\n// scope is intentionally excluded: it requires fallback logic and is handled separately.\nconst CELL_ATTRS = ['colspan', 'rowspan', 'headers', 'abbr'];\n\n/**\n * Sync text content and tracked attributes from a light-DOM marker to its\n * native mirror. `fallbackScope` is applied when the source element carries no\n * explicit `scope` attribute, ensuring the auto-inferred value is always\n * present and is restored if an explicit override is later removed.\n */\nfunction syncCell(source: Element, native: HTMLTableCellElement, fallbackScope?: string): void {\n if (source.childElementCount > 0) {\n // Source has element children: deep-clone them into the native cell so\n // components like ore-skeleton render correctly inside the shadow table.\n // Guard: skip re-clone if the serialised content is identical to avoid\n // redundant DOM work on every MutationObserver tick (e.g. 250+ cells\n // of skeleton loaders all cloning on each attribute change).\n const snapshot = source.innerHTML;\n\n if (native.getAttribute('data-src-html') === snapshot) return;\n\n native.setAttribute('data-src-html', snapshot);\n native.textContent = '';\n\n for (const child of source.childNodes) {\n native.appendChild(child.cloneNode(true));\n }\n } else {\n const text = source.textContent ?? '';\n\n if (native.textContent !== text) native.textContent = text;\n }\n\n for (const attr of CELL_ATTRS) {\n const val = source.getAttribute(attr);\n\n if (val !== null) native.setAttribute(attr, val);\n else native.removeAttribute(attr);\n }\n\n // scope: explicit attribute wins; otherwise restore the inferred fallback.\n const explicitScope = source.getAttribute('scope');\n\n if (explicitScope !== null) native.setAttribute('scope', explicitScope);\n else if (fallbackScope) native.scope = fallbackScope;\n else native.removeAttribute('scope');\n}\n\n/** Entry stored in the cell map: native mirror element + its inferred scope fallback. */\ntype CellEntry = { inferredScope: string | undefined; native: HTMLTableCellElement };\n\n/**\n * (Re)build the entire native shadow table from the current light-DOM markers.\n * Returns a WeakMap of source marker → CellEntry for targeted sync by the\n * content observer. Storing `inferredScope` per cell ensures that removing an\n * explicit `scope` attribute reverts to the auto-inferred value rather than\n * dropping it entirely.\n */\nfunction buildTable(\n host: HTMLElement,\n thead: HTMLTableSectionElement,\n tbody: HTMLTableSectionElement,\n tfoot: HTMLTableSectionElement,\n): WeakMap<Element, CellEntry> {\n const cellMap = new WeakMap<Element, CellEntry>();\n\n thead.textContent = '';\n tbody.textContent = '';\n tfoot.textContent = '';\n\n for (const child of host.children) {\n if (child.localName !== 'ore-tr') continue;\n\n const section = child.hasAttribute('head') ? thead : child.hasAttribute('foot') ? tfoot : tbody;\n const tr = document.createElement('tr');\n\n for (const cell of child.children) {\n if (cell.localName !== 'ore-th' && cell.localName !== 'ore-td') continue;\n\n const isHeader = cell.localName === 'ore-th';\n const native = document.createElement(isHeader ? 'th' : 'td');\n // Auto-infer scope for <th> elements; undefined for <td>.\n const inferredScope = isHeader ? (section === thead ? 'col' : 'row') : undefined;\n\n native.setAttribute('part', section === tbody ? 'cell' : 'header-cell');\n native.removeAttribute('data-src-html');\n syncCell(cell, native, inferredScope);\n cellMap.set(cell, { inferredScope, native });\n tr.appendChild(native);\n }\n\n section.appendChild(tr);\n }\n\n return cellMap;\n}\n\n/**\n * Data table component.\n *\n * Reads light-DOM `<ore-tr>`/`<ore-th>`/`<ore-td>` markers and projects them\n * into a fully-native shadow `<table>`. Cell attributes (`colspan`, `rowspan`,\n * `scope`, etc.) are mirrored. Changes are observed and synced incrementally.\n *\n * Native table features: sticky headers, colspan/rowspan, the table layout\n * algorithm: all work because the shadow tree contains real table elements.\n *\n * @element ore-table\n *\n * @attr {boolean} bordered - Thicker outer border\n * @attr {string} caption - Caption text shown above the table\n * @attr {boolean} fullwidth - Expands to 100% container width\n * @attr {boolean} loading - Busy state: reduced opacity, no pointer events\n * @attr {string} density - Cell density: 'compact' | 'cozy' | 'comfortable' (default: 'cozy')\n * @attr {boolean} sticky - Sticky `<thead>` with scroll container\n * @attr {boolean} striped - Alternating row backgrounds\n *\n * @part scroll - Scroll container that hosts the generated native table\n * @part table - Generated native `<table>` element\n * @part head - Generated native `<thead>` section\n * @part body - Generated native `<tbody>` section\n * @part foot - Generated native `<tfoot>` section\n * @part cell - Every native `<td>` in `<tbody>` rows\n * @part header-cell - Every native `<th>` / `<td>` in `<thead>` and `<tfoot>` rows\n *\n * @cssprop --table-bg - Table background color\n * @cssprop --table-border-color - Cell separator and outer border color\n * @cssprop --table-radius - Corner radius of the table container\n * @cssprop --table-shadow - Box shadow of the table container\n * @cssprop --table-header-bg - Background of header and footer rows\n * @cssprop --table-accent - Accent color for interactive states\n * @cssprop --table-row-hover-bg - Row hover background\n * @cssprop --table-stripe-bg - Even-row stripe background\n * @cssprop --table-cell-padding-x - Cell horizontal padding\n * @cssprop --table-cell-padding-y - Cell vertical padding\n * @cssprop --table-font-size - Base font size for cells\n * @cssprop --table-sticky-max-height - Max height of the sticky scroll container\n * @cssprop --table-sticky-header-bg - Background of sticky header cells\n * @cssprop --table-sticky-blur - Backdrop blur applied to sticky headers\n *\n * @example\n * ```html\n * <ore-table caption=\"Top repositories\" striped bordered sticky>\n * <ore-tr head>\n * <ore-th>Repository</ore-th>\n * <ore-th>Stars</ore-th>\n * </ore-tr>\n * <ore-tr>\n * <ore-td>vielzeug/refine</ore-td>\n * <ore-td>1 200</ore-td>\n * </ore-tr>\n * </ore-table>\n * ```\n */\nexport const TABLE_TAG = 'ore-table' as const;\ndefine<OreTableProps>(TABLE_TAG, {\n props: {\n bordered: prop.bool(false),\n caption: prop.string(),\n density: prop.string<'compact' | 'cozy' | 'comfortable'>(),\n fullwidth: prop.bool(false),\n loading: prop.bool(false),\n sticky: prop.bool(false),\n striped: prop.bool(false),\n },\n\n setup(props) {\n const el = getHost();\n const watch = watchEffect;\n\n bind({\n attr: {\n 'aria-busy': props.loading,\n 'aria-label': props.caption,\n },\n });\n\n // Build the native shadow table via DOM APIs (not innerHTML) to avoid\n // HTML-parser foster-parenting, which ejects table section elements from\n // their intended positions in the tree.\n onMounted(() => {\n const scrollContainer = el.shadowRoot?.querySelector('.scroll-container')!;\n\n const table = document.createElement('table');\n const captionEl = document.createElement('caption');\n const thead = document.createElement('thead');\n const tbody = document.createElement('tbody');\n const tfoot = document.createElement('tfoot');\n\n scrollContainer.setAttribute('part', 'scroll');\n table.setAttribute('part', 'table');\n thead.setAttribute('part', 'head');\n tbody.setAttribute('part', 'body');\n tfoot.setAttribute('part', 'foot');\n table.append(captionEl, thead, tbody, tfoot);\n scrollContainer.appendChild(table);\n\n // Reactively sync caption text and visibility from prop.\n watch(() => {\n const text = props.caption.value ?? '';\n\n captionEl.textContent = text;\n captionEl.hidden = text === '';\n });\n\n // Initial full build.\n let cellMap = buildTable(el, thead, tbody, tfoot);\n\n // Content observer: syncs text/attribute changes inside ore-th/ore-td.\n // Remains connected throughout the component lifetime: no\n // disconnect/reconnect during structural rebuilds. Records that arrive\n // for cells no longer in cellMap (after a rebuild) are silently ignored\n // by the `if (entry)` guard, so there is no correctness risk.\n const contentObserver = new MutationObserver((records) => {\n for (const rec of records) {\n const sourceCell = (rec.target instanceof Element ? rec.target : rec.target.parentElement)?.closest(\n 'ore-th, ore-td',\n );\n\n if (sourceCell) {\n const entry = cellMap.get(sourceCell);\n\n if (entry) syncCell(sourceCell, entry.native, entry.inferredScope);\n }\n }\n });\n\n contentObserver.observe(el, {\n // Include 'scope' in attributeFilter so explicit scope changes are picked\n // up and the fallback-restore logic in syncCell runs correctly.\n attributeFilter: [...CELL_ATTRS, 'scope'],\n attributes: true,\n characterData: true,\n childList: true,\n subtree: true,\n });\n\n // Structure observer: triggers a full rebuild when ore-tr elements are\n // added, removed, or reordered. Scoped to direct children only so it\n // never fires for cell-level mutations.\n const structureObserver = new MutationObserver(() => {\n cellMap = buildTable(el, thead, tbody, tfoot);\n });\n\n structureObserver.observe(el, { childList: true });\n\n return () => {\n structureObserver.disconnect();\n contentObserver.disconnect();\n };\n });\n\n return html`\n <div class=\"scroll-container\"></div>\n `;\n },\n\n styles: [reducedMotionMixin, tableBaseMixin('table'), componentStyles],\n});\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"table.cjs","names":[],"sources":["../src/content/table/table.ts"],"sourcesContent":["import { bind, define, getHost, html, onMounted, prop, watchEffect } from '@vielzeug/ore';\n\nimport { reducedMotionMixin, tableBaseMixin } from '../../styles';\nimport { DENSITY_LEVELS, type DensityLevel } from '../../types';\nimport componentStyles from './table.css?inline';\n\n/* ── Types ───────────────────────────────────────────────────────────────── */\n\n/** Table component properties */\nexport type OreTableProps = {\n /** Adds a thicker outer border */\n bordered?: boolean;\n /** Visible caption text: also used as the accessible table label via `aria-label` */\n caption?: string;\n /** Cell density: `'compact'` | `'cozy'` (default) | `'comfortable'` */\n density?: DensityLevel;\n /** Expands the table to 100% of its container width */\n fullwidth?: boolean;\n /** Applies a busy/disabled state with reduced opacity */\n loading?: boolean;\n /** Enables sticky column headers with a vertical scroll container */\n sticky?: boolean;\n /** Alternating row stripe backgrounds */\n striped?: boolean;\n};\n\n/* ── Child element markers ───────────────────────────────────────────────── */\n// ore-tr, ore-th, ore-td are lightweight light-DOM markers.\n// ore-table reads them and constructs a fully-native shadow <table> so that\n// browser features that require real table elements (colspan/rowspan,\n// position:sticky on <thead>, table layout algorithm) all work correctly.\n// Attributes on ore-th/ore-td are mirrored to the generated native cells.\n\n/**\n * Light-DOM row marker consumed by `<ore-table>`.\n *\n * @element ore-tr\n * @attr {boolean} head - Places the row in the generated `<thead>` section\n * @attr {boolean} foot - Places the row in the generated `<tfoot>` section\n *\n * @example\n * ```html\n * <ore-table>\n * <ore-tr head><ore-th>Name</ore-th><ore-th>Role</ore-th></ore-tr>\n * <ore-tr><ore-td>Alice</ore-td><ore-td>Admin</ore-td></ore-tr>\n * </ore-table>\n * ```\n */\nif (!customElements.get('ore-tr')) customElements.define('ore-tr', class extends HTMLElement {});\n\n/**\n * Light-DOM header cell marker consumed by `<ore-table>`.\n *\n * @element ore-th\n * @attr {number} colspan - Mirrors to native `<th colspan>`\n * @attr {number} rowspan - Mirrors to native `<th rowspan>`\n * @attr {string} scope - Mirrors to native `<th scope>`: 'col' | 'row' | 'colgroup' | 'rowgroup'\n * @attr {string} headers - Mirrors to native `<th headers>`\n *\n * @example\n * ```html\n * <ore-tr head>\n * <ore-th scope=\"col\">Name</ore-th>\n * <ore-th scope=\"col\" colspan=\"2\">Address</ore-th>\n * </ore-tr>\n * ```\n */\nif (!customElements.get('ore-th')) customElements.define('ore-th', class extends HTMLElement {});\n\n/**\n * Light-DOM data cell marker consumed by `<ore-table>`.\n *\n * @element ore-td\n * @attr {number} colspan - Mirrors to native `<td colspan>`\n * @attr {number} rowspan - Mirrors to native `<td rowspan>`\n * @attr {string} headers - Mirrors to native `<td headers>`\n *\n * @example\n * ```html\n * <ore-tr>\n * <ore-td>Alice</ore-td>\n * <ore-td colspan=\"2\">123 Main St, Springfield</ore-td>\n * </ore-tr>\n * ```\n */\nif (!customElements.get('ore-td')) customElements.define('ore-td', class extends HTMLElement {});\n\n/* ── Proxy/mirror helpers ────────────────────────────────────────────────── */\n\n// Attributes forwarded from ore-th/ore-td to the generated native cell.\n// scope is intentionally excluded: it requires fallback logic and is handled separately.\nconst CELL_ATTRS = ['colspan', 'rowspan', 'headers', 'abbr'];\n\n/**\n * Sync text content and tracked attributes from a light-DOM marker to its\n * native mirror. `fallbackScope` is applied when the source element carries no\n * explicit `scope` attribute, ensuring the auto-inferred value is always\n * present and is restored if an explicit override is later removed.\n */\nfunction syncCell(source: Element, native: HTMLTableCellElement, fallbackScope?: string): void {\n if (source.childElementCount > 0) {\n // Source has element children: deep-clone them into the native cell so\n // components like ore-skeleton render correctly inside the shadow table.\n // Guard: skip re-clone if the serialised content is identical to avoid\n // redundant DOM work on every MutationObserver tick (e.g. 250+ cells\n // of skeleton loaders all cloning on each attribute change).\n const snapshot = source.innerHTML;\n\n if (native.getAttribute('data-src-html') === snapshot) return;\n\n native.setAttribute('data-src-html', snapshot);\n native.textContent = '';\n\n for (const child of source.childNodes) {\n native.appendChild(child.cloneNode(true));\n }\n } else {\n const text = source.textContent ?? '';\n\n if (native.textContent !== text) native.textContent = text;\n }\n\n for (const attr of CELL_ATTRS) {\n const val = source.getAttribute(attr);\n\n if (val !== null) native.setAttribute(attr, val);\n else native.removeAttribute(attr);\n }\n\n // scope: explicit attribute wins; otherwise restore the inferred fallback.\n const explicitScope = source.getAttribute('scope');\n\n if (explicitScope !== null) native.setAttribute('scope', explicitScope);\n else if (fallbackScope) native.scope = fallbackScope;\n else native.removeAttribute('scope');\n}\n\n/** Entry stored in the cell map: native mirror element + its inferred scope fallback. */\ntype CellEntry = { inferredScope: string | undefined; native: HTMLTableCellElement };\n\n/**\n * (Re)build the entire native shadow table from the current light-DOM markers.\n * Returns a WeakMap of source marker → CellEntry for targeted sync by the\n * content observer. Storing `inferredScope` per cell ensures that removing an\n * explicit `scope` attribute reverts to the auto-inferred value rather than\n * dropping it entirely.\n */\nfunction buildTable(\n host: HTMLElement,\n thead: HTMLTableSectionElement,\n tbody: HTMLTableSectionElement,\n tfoot: HTMLTableSectionElement,\n): WeakMap<Element, CellEntry> {\n const cellMap = new WeakMap<Element, CellEntry>();\n\n thead.textContent = '';\n tbody.textContent = '';\n tfoot.textContent = '';\n\n for (const child of host.children) {\n if (child.localName !== 'ore-tr') continue;\n\n const section = child.hasAttribute('head') ? thead : child.hasAttribute('foot') ? tfoot : tbody;\n const tr = document.createElement('tr');\n\n for (const cell of child.children) {\n if (cell.localName !== 'ore-th' && cell.localName !== 'ore-td') continue;\n\n const isHeader = cell.localName === 'ore-th';\n const native = document.createElement(isHeader ? 'th' : 'td');\n // Auto-infer scope for <th> elements; undefined for <td>.\n const inferredScope = isHeader ? (section === thead ? 'col' : 'row') : undefined;\n\n native.setAttribute('part', section === tbody ? 'cell' : 'header-cell');\n native.removeAttribute('data-src-html');\n syncCell(cell, native, inferredScope);\n cellMap.set(cell, { inferredScope, native });\n tr.appendChild(native);\n }\n\n section.appendChild(tr);\n }\n\n return cellMap;\n}\n\n/**\n * Data table component.\n *\n * Reads light-DOM `<ore-tr>`/`<ore-th>`/`<ore-td>` markers and projects them\n * into a fully-native shadow `<table>`. Cell attributes (`colspan`, `rowspan`,\n * `scope`, etc.) are mirrored. Changes are observed and synced incrementally.\n *\n * Native table features: sticky headers, colspan/rowspan, the table layout\n * algorithm: all work because the shadow tree contains real table elements.\n *\n * @element ore-table\n *\n * @attr {boolean} bordered - Thicker outer border\n * @attr {string} caption - Caption text shown above the table\n * @attr {boolean} fullwidth - Expands to 100% container width\n * @attr {boolean} loading - Busy state: reduced opacity, no pointer events\n * @attr {string} density - Cell density: 'compact' | 'cozy' | 'comfortable' (default: 'cozy')\n * @attr {boolean} sticky - Sticky `<thead>` with scroll container\n * @attr {boolean} striped - Alternating row backgrounds\n *\n * @part scroll - Scroll container that hosts the generated native table\n * @part table - Generated native `<table>` element\n * @part head - Generated native `<thead>` section\n * @part body - Generated native `<tbody>` section\n * @part foot - Generated native `<tfoot>` section\n * @part cell - Every native `<td>` in `<tbody>` rows\n * @part header-cell - Every native `<th>` / `<td>` in `<thead>` and `<tfoot>` rows\n *\n * @cssprop --table-bg - Table background color\n * @cssprop --table-border-color - Cell separator and outer border color\n * @cssprop --table-radius - Corner radius of the table container\n * @cssprop --table-shadow - Box shadow of the table container\n * @cssprop --table-header-bg - Background of header and footer rows\n * @cssprop --table-accent - Accent color for interactive states\n * @cssprop --table-row-hover-bg - Row hover background\n * @cssprop --table-stripe-bg - Even-row stripe background\n * @cssprop --table-cell-padding-x - Cell horizontal padding\n * @cssprop --table-cell-padding-y - Cell vertical padding\n * @cssprop --table-font-size - Base font size for cells\n * @cssprop --table-sticky-max-height - Max height of the sticky scroll container\n * @cssprop --table-sticky-header-bg - Background of sticky header cells\n * @cssprop --table-sticky-blur - Backdrop blur applied to sticky headers\n *\n * @example\n * ```html\n * <ore-table caption=\"Top repositories\" striped bordered sticky>\n * <ore-tr head>\n * <ore-th>Repository</ore-th>\n * <ore-th>Stars</ore-th>\n * </ore-tr>\n * <ore-tr>\n * <ore-td>vielzeug/refine</ore-td>\n * <ore-td>1 200</ore-td>\n * </ore-tr>\n * </ore-table>\n * ```\n */\nexport const TABLE_TAG = 'ore-table' as const;\ndefine<OreTableProps>(TABLE_TAG, {\n props: {\n bordered: prop.bool(false),\n caption: prop.string(),\n density: prop.oneOf(DENSITY_LEVELS),\n fullwidth: prop.bool(false),\n loading: prop.bool(false),\n sticky: prop.bool(false),\n striped: prop.bool(false),\n },\n\n setup(props) {\n const el = getHost();\n const watch = watchEffect;\n\n bind({\n attr: {\n 'aria-busy': props.loading,\n 'aria-label': props.caption,\n },\n });\n\n // Build the native shadow table via DOM APIs (not innerHTML) to avoid\n // HTML-parser foster-parenting, which ejects table section elements from\n // their intended positions in the tree.\n onMounted(() => {\n const scrollContainer = el.shadowRoot?.querySelector('.scroll-container')!;\n\n const table = document.createElement('table');\n const captionEl = document.createElement('caption');\n const thead = document.createElement('thead');\n const tbody = document.createElement('tbody');\n const tfoot = document.createElement('tfoot');\n\n scrollContainer.setAttribute('part', 'scroll');\n table.setAttribute('part', 'table');\n thead.setAttribute('part', 'head');\n tbody.setAttribute('part', 'body');\n tfoot.setAttribute('part', 'foot');\n table.append(captionEl, thead, tbody, tfoot);\n scrollContainer.appendChild(table);\n\n // Reactively sync caption text and visibility from prop.\n watch(() => {\n const text = props.caption.value ?? '';\n\n captionEl.textContent = text;\n captionEl.hidden = text === '';\n });\n\n // Initial full build.\n let cellMap = buildTable(el, thead, tbody, tfoot);\n\n // Content observer: syncs text/attribute changes inside ore-th/ore-td.\n // Remains connected throughout the component lifetime: no\n // disconnect/reconnect during structural rebuilds. Records that arrive\n // for cells no longer in cellMap (after a rebuild) are silently ignored\n // by the `if (entry)` guard, so there is no correctness risk.\n const contentObserver = new MutationObserver((records) => {\n for (const rec of records) {\n const sourceCell = (rec.target instanceof Element ? rec.target : rec.target.parentElement)?.closest(\n 'ore-th, ore-td',\n );\n\n if (sourceCell) {\n const entry = cellMap.get(sourceCell);\n\n if (entry) syncCell(sourceCell, entry.native, entry.inferredScope);\n }\n }\n });\n\n contentObserver.observe(el, {\n // Include 'scope' in attributeFilter so explicit scope changes are picked\n // up and the fallback-restore logic in syncCell runs correctly.\n attributeFilter: [...CELL_ATTRS, 'scope'],\n attributes: true,\n characterData: true,\n childList: true,\n subtree: true,\n });\n\n // Structure observer: triggers a full rebuild when ore-tr elements are\n // added, removed, or reordered. Scoped to direct children only so it\n // never fires for cell-level mutations.\n const structureObserver = new MutationObserver(() => {\n cellMap = buildTable(el, thead, tbody, tfoot);\n });\n\n structureObserver.observe(el, { childList: true });\n\n return () => {\n structureObserver.disconnect();\n contentObserver.disconnect();\n };\n });\n\n return html`\n <div class=\"scroll-container\"></div>\n `;\n },\n\n styles: [reducedMotionMixin, tableBaseMixin('table'), componentStyles],\n});\n"],"mappings":"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"}
|
package/dist/table.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import{reducedMotionMixin as e}from"./styles/mixins/accessibility.css.js";import{tableBaseMixin as t}from"./styles/mixins/table-base.css.js";import n from"./content/table/table.css.js";import{bind as
|
|
1
|
+
import{reducedMotionMixin as e}from"./styles/mixins/accessibility.css.js";import{tableBaseMixin as t}from"./styles/mixins/table-base.css.js";import{DENSITY_LEVELS as n}from"./shared/types.js";import r from"./content/table/table.css.js";import{bind as i,define as a,getHost as o,html as s,onMounted as c,prop as l,watchEffect as u}from"@vielzeug/ore";customElements.get(`ore-tr`)||customElements.define(`ore-tr`,class extends HTMLElement{}),customElements.get(`ore-th`)||customElements.define(`ore-th`,class extends HTMLElement{}),customElements.get(`ore-td`)||customElements.define(`ore-td`,class extends HTMLElement{});var d=[`colspan`,`rowspan`,`headers`,`abbr`];function syncCell(e,t,n){if(e.childElementCount>0){let n=e.innerHTML;if(t.getAttribute(`data-src-html`)===n)return;t.setAttribute(`data-src-html`,n),t.textContent=``;for(let n of e.childNodes)t.appendChild(n.cloneNode(!0))}else{let n=e.textContent??``;t.textContent!==n&&(t.textContent=n)}for(let n of d){let r=e.getAttribute(n);r===null?t.removeAttribute(n):t.setAttribute(n,r)}let r=e.getAttribute(`scope`);r===null?n?t.scope=n:t.removeAttribute(`scope`):t.setAttribute(`scope`,r)}function buildTable(e,t,n,r){let i=new WeakMap;t.textContent=``,n.textContent=``,r.textContent=``;for(let a of e.children){if(a.localName!==`ore-tr`)continue;let e=a.hasAttribute(`head`)?t:a.hasAttribute(`foot`)?r:n,o=document.createElement(`tr`);for(let r of a.children){if(r.localName!==`ore-th`&&r.localName!==`ore-td`)continue;let a=r.localName===`ore-th`,s=document.createElement(a?`th`:`td`),c=a?e===t?`col`:`row`:void 0;s.setAttribute(`part`,e===n?`cell`:`header-cell`),s.removeAttribute(`data-src-html`),syncCell(r,s,c),i.set(r,{inferredScope:c,native:s}),o.appendChild(s)}e.appendChild(o)}return i}var f=`ore-table`;a(f,{props:{bordered:l.bool(!1),caption:l.string(),density:l.oneOf(n),fullwidth:l.bool(!1),loading:l.bool(!1),sticky:l.bool(!1),striped:l.bool(!1)},setup(e){let t=o(),n=u;return i({attr:{"aria-busy":e.loading,"aria-label":e.caption}}),c(()=>{let r=t.shadowRoot?.querySelector(`.scroll-container`),i=document.createElement(`table`),a=document.createElement(`caption`),o=document.createElement(`thead`),s=document.createElement(`tbody`),c=document.createElement(`tfoot`);r.setAttribute(`part`,`scroll`),i.setAttribute(`part`,`table`),o.setAttribute(`part`,`head`),s.setAttribute(`part`,`body`),c.setAttribute(`part`,`foot`),i.append(a,o,s,c),r.appendChild(i),n(()=>{let t=e.caption.value??``;a.textContent=t,a.hidden=t===``});let l=buildTable(t,o,s,c),u=new MutationObserver(e=>{for(let t of e){let e=(t.target instanceof Element?t.target:t.target.parentElement)?.closest(`ore-th, ore-td`);if(e){let t=l.get(e);t&&syncCell(e,t.native,t.inferredScope)}}});u.observe(t,{attributeFilter:[...d,`scope`],attributes:!0,characterData:!0,childList:!0,subtree:!0});let f=new MutationObserver(()=>{l=buildTable(t,o,s,c)});return f.observe(t,{childList:!0}),()=>{f.disconnect(),u.disconnect()}}),s`
|
|
2
2
|
<div class="scroll-container"></div>
|
|
3
|
-
`},styles:[e,t(`table`),
|
|
3
|
+
`},styles:[e,t(`table`),r]});export{f as TABLE_TAG};
|
|
4
4
|
//# sourceMappingURL=table.js.map
|