kanto-ds 1.2.0 → 1.3.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (95) hide show
  1. package/README.md +21 -3
  2. package/dist/chunks/index-fzPIgxe2.js +74 -0
  3. package/dist/chunks/index-fzPIgxe2.js.map +1 -0
  4. package/dist/chunks/kt-element-mdd5cXZX.js +52 -0
  5. package/dist/chunks/kt-element-mdd5cXZX.js.map +1 -0
  6. package/dist/components/core/kt-avatar/kt-avatar.js +8 -7
  7. package/dist/components/core/kt-avatar/kt-avatar.js.map +1 -1
  8. package/dist/components/core/kt-badge/kt-badge.js +7 -6
  9. package/dist/components/core/kt-badge/kt-badge.js.map +1 -1
  10. package/dist/components/core/kt-button/kt-button.js +1 -1
  11. package/dist/components/core/kt-card/kt-card.js +1 -1
  12. package/dist/components/core/kt-code/kt-code.js +31 -30
  13. package/dist/components/core/kt-code/kt-code.js.map +1 -1
  14. package/dist/components/core/kt-icon/kt-icon.js +1 -1
  15. package/dist/components/core/kt-kbd/kt-kbd.js +1 -1
  16. package/dist/components/core/kt-split-button/kt-split-button.d.ts +2 -2
  17. package/dist/components/core/kt-split-button/kt-split-button.js +27 -26
  18. package/dist/components/core/kt-split-button/kt-split-button.js.map +1 -1
  19. package/dist/components/data/kt-chart/kt-chart.d.ts +2 -2
  20. package/dist/components/data/kt-chart/kt-chart.js +205 -204
  21. package/dist/components/data/kt-chart/kt-chart.js.map +1 -1
  22. package/dist/components/data/kt-meter/kt-meter.js +1 -1
  23. package/dist/components/data/kt-pagination/kt-pagination.d.ts +1 -1
  24. package/dist/components/data/kt-pagination/kt-pagination.js +29 -28
  25. package/dist/components/data/kt-pagination/kt-pagination.js.map +1 -1
  26. package/dist/components/data/kt-stat/kt-stat.js +1 -1
  27. package/dist/components/data/kt-table/kt-table.d.ts +2 -2
  28. package/dist/components/data/kt-table/kt-table.js +30 -29
  29. package/dist/components/data/kt-table/kt-table.js.map +1 -1
  30. package/dist/components/data/kt-timeline/kt-timeline.js +1 -1
  31. package/dist/components/feedback/kt-alert/kt-alert.js +17 -16
  32. package/dist/components/feedback/kt-alert/kt-alert.js.map +1 -1
  33. package/dist/components/feedback/kt-empty-state/kt-empty-state.js +1 -1
  34. package/dist/components/feedback/kt-progress-bar/kt-progress-bar.js +1 -1
  35. package/dist/components/feedback/kt-skeleton/kt-skeleton.js +1 -1
  36. package/dist/components/feedback/kt-toast/kt-toast.js +25 -19
  37. package/dist/components/feedback/kt-toast/kt-toast.js.map +1 -1
  38. package/dist/components/feedback/kt-toast-container/kt-toast-container.js +1 -1
  39. package/dist/components/feedback/kt-tooltip/kt-tooltip.js +1 -1
  40. package/dist/components/forms/kt-drag-drop/kt-drag-drop.d.ts +2 -2
  41. package/dist/components/forms/kt-drag-drop/kt-drag-drop.js +60 -57
  42. package/dist/components/forms/kt-drag-drop/kt-drag-drop.js.map +1 -1
  43. package/dist/components/forms/kt-form/kt-form.js +1 -1
  44. package/dist/components/forms/kt-input/kt-input.js +56 -55
  45. package/dist/components/forms/kt-input/kt-input.js.map +1 -1
  46. package/dist/components/forms/kt-input-menu/kt-input-menu.d.ts +1 -1
  47. package/dist/components/forms/kt-input-menu/kt-input-menu.js +57 -56
  48. package/dist/components/forms/kt-input-menu/kt-input-menu.js.map +1 -1
  49. package/dist/components/forms/kt-label-input/kt-label-input.js +1 -1
  50. package/dist/components/forms/kt-select/kt-select.d.ts +2 -2
  51. package/dist/components/forms/kt-select/kt-select.js +62 -61
  52. package/dist/components/forms/kt-select/kt-select.js.map +1 -1
  53. package/dist/components/forms/kt-textarea/kt-textarea.js +9 -8
  54. package/dist/components/forms/kt-textarea/kt-textarea.js.map +1 -1
  55. package/dist/components/forms/kt-toggle/kt-toggle.js +1 -1
  56. package/dist/components/navigation/kt-breadcrumb/kt-breadcrumb.d.ts +1 -1
  57. package/dist/components/navigation/kt-breadcrumb/kt-breadcrumb.js +6 -5
  58. package/dist/components/navigation/kt-breadcrumb/kt-breadcrumb.js.map +1 -1
  59. package/dist/components/navigation/kt-header/kt-header.js +11 -10
  60. package/dist/components/navigation/kt-header/kt-header.js.map +1 -1
  61. package/dist/components/navigation/kt-page-header/kt-page-header.js +1 -1
  62. package/dist/components/navigation/kt-segmented-control/kt-segmented-control.js +44 -43
  63. package/dist/components/navigation/kt-segmented-control/kt-segmented-control.js.map +1 -1
  64. package/dist/components/navigation/kt-sub-menu-navigation/kt-sub-menu-navigation.d.ts +1 -1
  65. package/dist/components/navigation/kt-sub-menu-navigation/kt-sub-menu-navigation.js +6 -5
  66. package/dist/components/navigation/kt-sub-menu-navigation/kt-sub-menu-navigation.js.map +1 -1
  67. package/dist/components/navigation/kt-tabs/kt-tabs.js +1 -1
  68. package/dist/components/navigation/kt-toggle-button/kt-toggle-button.js +1 -1
  69. package/dist/components/navigation/kt-toggle-button-group/kt-toggle-button-group.js +1 -1
  70. package/dist/components/overlays/kt-collapsible/kt-collapsible.js +1 -1
  71. package/dist/components/overlays/kt-confirm-dialog/kt-confirm-dialog.d.ts +3 -3
  72. package/dist/components/overlays/kt-confirm-dialog/kt-confirm-dialog.js +30 -27
  73. package/dist/components/overlays/kt-confirm-dialog/kt-confirm-dialog.js.map +1 -1
  74. package/dist/components/overlays/kt-dropdown/kt-dropdown.d.ts +1 -1
  75. package/dist/components/overlays/kt-dropdown/kt-dropdown.js +8 -7
  76. package/dist/components/overlays/kt-dropdown/kt-dropdown.js.map +1 -1
  77. package/dist/components/overlays/kt-modal/kt-modal.js +5 -4
  78. package/dist/components/overlays/kt-modal/kt-modal.js.map +1 -1
  79. package/dist/components/overlays/kt-side-panel/kt-side-panel.d.ts +1 -1
  80. package/dist/components/overlays/kt-side-panel/kt-side-panel.js +24 -23
  81. package/dist/components/overlays/kt-side-panel/kt-side-panel.js.map +1 -1
  82. package/dist/custom-elements.json +76 -76
  83. package/dist/index.d.ts +1 -0
  84. package/dist/index.js +24 -19
  85. package/dist/index.js.map +1 -1
  86. package/dist/internal/kt-element.d.ts +6 -1
  87. package/dist/internal/strings.d.ts +93 -0
  88. package/dist/strings/index.d.ts +11 -0
  89. package/dist/strings/index.js +8 -0
  90. package/dist/strings/index.js.map +1 -0
  91. package/dist/tokens/base.css +53 -0
  92. package/dist/web-types.json +39 -39
  93. package/package.json +11 -3
  94. package/dist/chunks/kt-element-B_jjQDhg.js +0 -38
  95. package/dist/chunks/kt-element-B_jjQDhg.js.map +0 -1
@@ -1 +1 @@
1
- {"version":3,"file":"kt-select.js","sources":["../../../../src/components/forms/kt-select/kt-select.ts"],"sourcesContent":["import { css, html, nothing, type PropertyValues, type TemplateResult } from 'lit';\nimport { property, state } from 'lit/decorators.js';\nimport { classMap } from 'lit/directives/class-map.js';\nimport { KtElement, defineElement } from '#internal/kt-element';\nimport { emit, uniqueId } from '#internal/events';\nimport {\n attachFormInternals,\n setFormValue,\n setValidity,\n type UsableInternals,\n} from '#internal/form-control';\nimport {\n firstEnabledIndex,\n lastEnabledIndex,\n listboxStyles,\n nextEnabledIndex,\n optionLabel,\n type KtOption,\n} from '#internal/listbox';\nimport '../../core/kt-icon/kt-icon.js';\n\nexport type KtSelectSize = 'small' | 'medium' | 'large';\nexport type { KtOption };\n\n/**\n * A single-choice dropdown.\n *\n * Unlike the trigger-plus-div it replaces, this is a real listbox: arrow keys\n * move an active descendant, Home and End jump to the ends, Enter commits,\n * Escape closes without changing anything, and disabled options are skipped\n * rather than merely unclickable.\n *\n * @element kt-select\n *\n * @csspart trigger - The button that opens the list.\n * @csspart popup - The option list.\n * @csspart option - An option row.\n *\n * @fires kt-change - An option was chosen or cleared.\n * `detail: { value, option }`.\n *\n * @example\n * ```html\n * <kt-select placeholder=\"Select a region\"></kt-select>\n * ```\n * ```js\n * select.options = [{ id: 'ne', label: 'North East' }, { id: 'sw', label: 'South West' }];\n * ```\n */\nexport class KtSelect extends KtElement {\n static readonly formAssociated = true;\n\n static override styles = [\n KtElement.styles,\n listboxStyles,\n css`\n :host {\n position: relative;\n display: block;\n --field-height: var(--button-height);\n }\n\n :host([size='small']) {\n --field-height: var(--button-height-small);\n }\n :host([size='large']) {\n --field-height: var(--button-height-large);\n }\n\n .trigger {\n display: grid;\n grid-template-columns: 1fr auto;\n align-items: center;\n gap: var(--gap-element);\n width: 100%;\n height: var(--field-height);\n padding: 0 var(--button-padding-x);\n color: var(--text-body);\n font: var(--font-input);\n text-align: left;\n background-color: var(--color-dark-20);\n border: none;\n border-radius: var(--radius-input);\n /* A resting hairline. A field is a fill on --surface-field, which is\n one ramp step from the page in dark and almost the same colour in\n light — so on a card or inside a modal it simply disappeared and\n read as a bare native control.\n\n A border rather than an outline, because the control inside fills\n the field exactly and a coincident outline is painted over by the\n native widget. A border insets the control by its own width, so it\n cannot be covered. box-sizing: border-box keeps the outer size.\n\n The hover and focus rings stay outlines on top of it, and the\n transparent resting outline is what they animate from: without it\n outline-color starts at the initial value, which resolves to the\n text colour, and hover flashed near-white before settling. */\n border: var(--border-width) solid var(--border-field);\n outline: var(--outline-width) solid transparent;\n cursor: pointer;\n transition:\n background-color var(--duration-instant),\n outline-color var(--duration-instant);\n }\n\n .trigger:hover {\n outline: var(--outline-width) solid var(--color-text-700);\n }\n .trigger:focus-visible,\n .open .trigger {\n background-color: var(--color-dark-12);\n outline: var(--outline-width) solid var(--color-primary-base);\n }\n\n .error .trigger,\n .error .trigger:hover {\n outline: var(--outline-width) solid var(--color-danger-base);\n }\n\n :host([disabled]) {\n pointer-events: none;\n }\n :host([disabled]) .trigger {\n color: var(--text-disabled);\n background-color: var(--color-dark-14);\n }\n\n .value {\n overflow: hidden;\n white-space: nowrap;\n text-overflow: ellipsis;\n }\n\n .placeholder {\n color: var(--text-muted);\n }\n\n .icons {\n display: inline-flex;\n align-items: center;\n gap: var(--gap-element);\n }\n\n .clear {\n display: inline-flex;\n padding: 0;\n color: inherit;\n background: none;\n border: none;\n cursor: pointer;\n transition: transform var(--duration-instant) ease-in-out;\n }\n .clear:hover {\n transform: rotate(90deg);\n }\n\n .chevron {\n display: inline-flex;\n align-items: center;\n transition: transform var(--duration-fast) ease-in-out;\n }\n .open .chevron {\n transform: scaleY(-1);\n }\n `,\n ];\n\n private internals: UsableInternals | null = null;\n private defaultValue: string | number | null = null;\n private readonly listId = uniqueId('kt-select-list');\n\n @state()\n private open = false;\n\n /** Index of the active descendant while the list is open; -1 for none. */\n @state()\n private activeIndex = -1;\n\n /** The options to choose from. A property: this is data, not an attribute. */\n @property({ attribute: false })\n options: readonly KtOption[] = [];\n\n /** The selected option's id, or `null`. */\n @property({ type: String })\n value: string | number | null = null;\n\n @property({ type: String })\n placeholder = 'Select';\n\n @property({ type: String })\n name = '';\n\n @property({ type: String, reflect: true })\n size: KtSelectSize = 'medium';\n\n @property({ type: Boolean, reflect: true })\n disabled = false;\n\n @property({ type: Boolean, reflect: true })\n required = false;\n\n /** Error message. A non-empty value puts the control in its error state. */\n @property({ type: String, reflect: true })\n error = '';\n\n /** Shows the clear button once something is selected. */\n @property({ type: Boolean })\n clearable = true;\n\n /** Accessible name, when no `<kt-label-input>` wraps the control. */\n @property({ type: String })\n label = '';\n\n /** Shown when `options` is empty. */\n @property({ type: String, attribute: 'empty-text' })\n emptyText = 'No options available';\n\n override connectedCallback(): void {\n super.connectedCallback();\n this.internals ??= attachFormInternals(this);\n this.defaultValue = this.value;\n document.addEventListener('pointerdown', this.onDocumentPointerDown);\n }\n\n override disconnectedCallback(): void {\n super.disconnectedCallback();\n document.removeEventListener('pointerdown', this.onDocumentPointerDown);\n }\n\n override willUpdate(changed: PropertyValues<this>): void {\n if (changed.has('value') || changed.has('required') || changed.has('error')) {\n setFormValue(this.internals, this.value === null ? null : String(this.value));\n\n const missing = this.required && this.value === null;\n setValidity(\n this.internals,\n { valueMissing: missing, customError: Boolean(this.error) },\n this.error || (missing ? 'Select an option.' : ''),\n );\n }\n }\n\n formResetCallback(): void {\n this.value = this.defaultValue;\n this.open = false;\n }\n\n formStateRestoreCallback(state: string): void {\n this.value = state;\n }\n\n override focus(options?: FocusOptions): void {\n this.shadowRoot?.querySelector<HTMLButtonElement>('.trigger')?.focus(options);\n }\n\n /** The currently selected option, if the id still matches one. */\n get selectedOption(): KtOption | undefined {\n return this.options.find((option) => option.id === this.value);\n }\n\n private onDocumentPointerDown = (event: Event): void => {\n if (event.composedPath().includes(this)) return;\n this.open = false;\n };\n\n private openList(): void {\n if (this.disabled) return;\n this.open = true;\n const selected = this.options.findIndex((option) => option.id === this.value);\n this.activeIndex = selected >= 0 ? selected : firstEnabledIndex(this.options);\n }\n\n private closeList(): void {\n this.open = false;\n this.activeIndex = -1;\n }\n\n private toggleList(): void {\n if (this.open) this.closeList();\n else this.openList();\n }\n\n private choose(option: KtOption): void {\n if (option.disabled) return;\n this.value = option.id;\n this.closeList();\n this.focus();\n emit(this, 'kt-change', { value: option.id, option });\n }\n\n private clear(event: Event): void {\n event.stopPropagation();\n this.value = null;\n emit(this, 'kt-change', { value: null, option: null });\n }\n\n private onKeyDown(event: KeyboardEvent): void {\n switch (event.key) {\n case 'ArrowDown':\n case 'ArrowUp': {\n event.preventDefault();\n if (!this.open) return this.openList();\n this.activeIndex = nextEnabledIndex(\n this.options,\n this.activeIndex,\n event.key === 'ArrowDown' ? 1 : -1,\n );\n return;\n }\n case 'Home':\n if (!this.open) return;\n event.preventDefault();\n this.activeIndex = firstEnabledIndex(this.options);\n return;\n case 'End':\n if (!this.open) return;\n event.preventDefault();\n this.activeIndex = lastEnabledIndex(this.options);\n return;\n case 'Enter':\n case ' ': {\n event.preventDefault();\n if (!this.open) return this.openList();\n const option = this.options[this.activeIndex];\n if (option) this.choose(option);\n return;\n }\n case 'Escape':\n if (!this.open) return;\n event.stopPropagation();\n this.closeList();\n return;\n case 'Tab':\n this.closeList();\n }\n }\n\n private optionId(index: number): string {\n return `${this.listId}-option-${index}`;\n }\n\n override render(): TemplateResult {\n const selected = this.selectedOption;\n const showClear = this.clearable && selected !== undefined && !this.disabled;\n\n return html`<div\n class=${classMap({ open: this.open, error: Boolean(this.error) })}\n @keydown=${this.onKeyDown}\n >\n <button\n part=\"trigger\"\n type=\"button\"\n class=\"trigger\"\n role=\"combobox\"\n aria-haspopup=\"listbox\"\n aria-expanded=${this.open ? 'true' : 'false'}\n aria-controls=${this.listId}\n aria-activedescendant=${\n this.open && this.activeIndex >= 0 ? this.optionId(this.activeIndex) : nothing\n }\n aria-label=${this.label || nothing}\n aria-invalid=${this.error ? 'true' : nothing}\n ?disabled=${this.disabled}\n @click=${this.toggleList}\n >\n <span class=${classMap({ value: true, placeholder: !selected })}>\n ${selected ? optionLabel(selected) : this.placeholder}\n </span>\n <span class=\"icons\">\n ${\n showClear\n ? html`<span\n class=\"clear\"\n role=\"button\"\n tabindex=\"-1\"\n aria-label=\"Clear\"\n @click=${this.clear}\n >\n <kt-icon name=\"x\" size=\"18\"></kt-icon>\n </span>`\n : nothing\n }\n <span class=\"chevron\"><kt-icon name=\"chevron-down\" size=\"18\"></kt-icon></span>\n </span>\n </button>\n\n <ul\n part=\"popup\"\n id=${this.listId}\n class=${classMap({ popup: true, open: this.open })}\n role=\"listbox\"\n aria-label=${this.label || this.placeholder}\n >\n ${\n this.options.length === 0\n ? html`<li class=\"empty\">${this.emptyText}</li>`\n : this.options.map(\n (option, index) =>\n html`<li\n part=\"option\"\n id=${this.optionId(index)}\n class=${classMap({\n option: true,\n selected: option.id === this.value,\n active: index === this.activeIndex,\n disabled: Boolean(option.disabled),\n })}\n role=\"option\"\n aria-selected=${option.id === this.value ? 'true' : 'false'}\n aria-disabled=${option.disabled ? 'true' : nothing}\n @click=${() => this.choose(option)}\n >\n ${optionLabel(option)}\n </li>`,\n )\n }\n </ul>\n </div>`;\n }\n}\n\ndefineElement('kt-select', KtSelect);\n\ndeclare global {\n interface HTMLElementTagNameMap {\n 'kt-select': KtSelect;\n }\n}\n"],"names":["KtSelect","KtElement","uniqueId","event","listboxStyles","css","attachFormInternals","changed","setFormValue","missing","setValidity","state","options","option","selected","firstEnabledIndex","emit","nextEnabledIndex","lastEnabledIndex","index","showClear","html","classMap","nothing","optionLabel","__decorateClass","property","defineElement"],"mappings":"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"}
1
+ {"version":3,"file":"kt-select.js","sources":["../../../../src/components/forms/kt-select/kt-select.ts"],"sourcesContent":["import { css, html, nothing, type PropertyValues, type TemplateResult } from 'lit';\nimport { property, state } from 'lit/decorators.js';\nimport { classMap } from 'lit/directives/class-map.js';\nimport { KtElement, defineElement } from '#internal/kt-element';\nimport { emit, uniqueId } from '#internal/events';\nimport {\n attachFormInternals,\n setFormValue,\n setValidity,\n type UsableInternals,\n} from '#internal/form-control';\nimport {\n firstEnabledIndex,\n lastEnabledIndex,\n listboxStyles,\n nextEnabledIndex,\n optionLabel,\n type KtOption,\n} from '#internal/listbox';\nimport { strings } from '#internal/strings';\nimport '../../core/kt-icon/kt-icon.js';\n\nexport type KtSelectSize = 'small' | 'medium' | 'large';\nexport type { KtOption };\n\n/**\n * A single-choice dropdown.\n *\n * Unlike the trigger-plus-div it replaces, this is a real listbox: arrow keys\n * move an active descendant, Home and End jump to the ends, Enter commits,\n * Escape closes without changing anything, and disabled options are skipped\n * rather than merely unclickable.\n *\n * @element kt-select\n *\n * @csspart trigger - The button that opens the list.\n * @csspart popup - The option list.\n * @csspart option - An option row.\n *\n * @fires kt-change - An option was chosen or cleared.\n * `detail: { value, option }`.\n *\n * @example\n * ```html\n * <kt-select placeholder=\"Select a region\"></kt-select>\n * ```\n * ```js\n * select.options = [{ id: 'ne', label: 'North East' }, { id: 'sw', label: 'South West' }];\n * ```\n */\nexport class KtSelect extends KtElement {\n static readonly formAssociated = true;\n\n static override styles = [\n KtElement.styles,\n listboxStyles,\n css`\n :host {\n position: relative;\n display: block;\n --field-height: var(--button-height);\n }\n\n :host([size='small']) {\n --field-height: var(--button-height-small);\n }\n :host([size='large']) {\n --field-height: var(--button-height-large);\n }\n\n .trigger {\n display: grid;\n grid-template-columns: 1fr auto;\n align-items: center;\n gap: var(--gap-element);\n width: 100%;\n height: var(--field-height);\n padding: 0 var(--button-padding-x);\n color: var(--text-body);\n font: var(--font-input);\n text-align: left;\n background-color: var(--color-dark-20);\n border: none;\n border-radius: var(--radius-input);\n /* A resting hairline. A field is a fill on --surface-field, which is\n one ramp step from the page in dark and almost the same colour in\n light — so on a card or inside a modal it simply disappeared and\n read as a bare native control.\n\n A border rather than an outline, because the control inside fills\n the field exactly and a coincident outline is painted over by the\n native widget. A border insets the control by its own width, so it\n cannot be covered. box-sizing: border-box keeps the outer size.\n\n The hover and focus rings stay outlines on top of it, and the\n transparent resting outline is what they animate from: without it\n outline-color starts at the initial value, which resolves to the\n text colour, and hover flashed near-white before settling. */\n border: var(--border-width) solid var(--border-field);\n outline: var(--outline-width) solid transparent;\n cursor: pointer;\n transition:\n background-color var(--duration-instant),\n outline-color var(--duration-instant);\n }\n\n .trigger:hover {\n outline: var(--outline-width) solid var(--color-text-700);\n }\n .trigger:focus-visible,\n .open .trigger {\n background-color: var(--color-dark-12);\n outline: var(--outline-width) solid var(--color-primary-base);\n }\n\n .error .trigger,\n .error .trigger:hover {\n outline: var(--outline-width) solid var(--color-danger-base);\n }\n\n :host([disabled]) {\n pointer-events: none;\n }\n :host([disabled]) .trigger {\n color: var(--text-disabled);\n background-color: var(--color-dark-14);\n }\n\n .value {\n overflow: hidden;\n white-space: nowrap;\n text-overflow: ellipsis;\n }\n\n .placeholder {\n color: var(--text-muted);\n }\n\n .icons {\n display: inline-flex;\n align-items: center;\n gap: var(--gap-element);\n }\n\n .clear {\n display: inline-flex;\n padding: 0;\n color: inherit;\n background: none;\n border: none;\n cursor: pointer;\n transition: transform var(--duration-instant) ease-in-out;\n }\n .clear:hover {\n transform: rotate(90deg);\n }\n\n .chevron {\n display: inline-flex;\n align-items: center;\n transition: transform var(--duration-fast) ease-in-out;\n }\n .open .chevron {\n transform: scaleY(-1);\n }\n `,\n ];\n\n private internals: UsableInternals | null = null;\n private defaultValue: string | number | null = null;\n private readonly listId = uniqueId('kt-select-list');\n\n @state()\n private open = false;\n\n /** Index of the active descendant while the list is open; -1 for none. */\n @state()\n private activeIndex = -1;\n\n /** The options to choose from. A property: this is data, not an attribute. */\n @property({ attribute: false })\n options: readonly KtOption[] = [];\n\n /** The selected option's id, or `null`. */\n @property({ type: String })\n value: string | number | null = null;\n\n @property({ type: String })\n placeholder: string | undefined = undefined;\n\n @property({ type: String })\n name = '';\n\n @property({ type: String, reflect: true })\n size: KtSelectSize = 'medium';\n\n @property({ type: Boolean, reflect: true })\n disabled = false;\n\n @property({ type: Boolean, reflect: true })\n required = false;\n\n /** Error message. A non-empty value puts the control in its error state. */\n @property({ type: String, reflect: true })\n error = '';\n\n /** Shows the clear button once something is selected. */\n @property({ type: Boolean })\n clearable = true;\n\n /** Accessible name, when no `<kt-label-input>` wraps the control. */\n @property({ type: String })\n label = '';\n\n /** Shown when `options` is empty. */\n @property({ type: String, attribute: 'empty-text' })\n emptyText: string | undefined = undefined;\n\n override connectedCallback(): void {\n super.connectedCallback();\n this.internals ??= attachFormInternals(this);\n this.defaultValue = this.value;\n document.addEventListener('pointerdown', this.onDocumentPointerDown);\n }\n\n override disconnectedCallback(): void {\n super.disconnectedCallback();\n document.removeEventListener('pointerdown', this.onDocumentPointerDown);\n }\n\n override willUpdate(changed: PropertyValues<this>): void {\n if (\n changed.has('value') ||\n changed.has('required') ||\n changed.has('error') ||\n this.stringsChanged(changed)\n ) {\n setFormValue(this.internals, this.value === null ? null : String(this.value));\n\n const missing = this.required && this.value === null;\n setValidity(\n this.internals,\n { valueMissing: missing, customError: Boolean(this.error) },\n this.error || (missing ? strings().selectOption : ''),\n );\n }\n }\n\n formResetCallback(): void {\n this.value = this.defaultValue;\n this.open = false;\n }\n\n formStateRestoreCallback(state: string): void {\n this.value = state;\n }\n\n override focus(options?: FocusOptions): void {\n this.shadowRoot?.querySelector<HTMLButtonElement>('.trigger')?.focus(options);\n }\n\n /** The currently selected option, if the id still matches one. */\n get selectedOption(): KtOption | undefined {\n return this.options.find((option) => option.id === this.value);\n }\n\n private onDocumentPointerDown = (event: Event): void => {\n if (event.composedPath().includes(this)) return;\n this.open = false;\n };\n\n private openList(): void {\n if (this.disabled) return;\n this.open = true;\n const selected = this.options.findIndex((option) => option.id === this.value);\n this.activeIndex = selected >= 0 ? selected : firstEnabledIndex(this.options);\n }\n\n private closeList(): void {\n this.open = false;\n this.activeIndex = -1;\n }\n\n private toggleList(): void {\n if (this.open) this.closeList();\n else this.openList();\n }\n\n private choose(option: KtOption): void {\n if (option.disabled) return;\n this.value = option.id;\n this.closeList();\n this.focus();\n emit(this, 'kt-change', { value: option.id, option });\n }\n\n private clear(event: Event): void {\n event.stopPropagation();\n this.value = null;\n emit(this, 'kt-change', { value: null, option: null });\n }\n\n private onKeyDown(event: KeyboardEvent): void {\n switch (event.key) {\n case 'ArrowDown':\n case 'ArrowUp': {\n event.preventDefault();\n if (!this.open) return this.openList();\n this.activeIndex = nextEnabledIndex(\n this.options,\n this.activeIndex,\n event.key === 'ArrowDown' ? 1 : -1,\n );\n return;\n }\n case 'Home':\n if (!this.open) return;\n event.preventDefault();\n this.activeIndex = firstEnabledIndex(this.options);\n return;\n case 'End':\n if (!this.open) return;\n event.preventDefault();\n this.activeIndex = lastEnabledIndex(this.options);\n return;\n case 'Enter':\n case ' ': {\n event.preventDefault();\n if (!this.open) return this.openList();\n const option = this.options[this.activeIndex];\n if (option) this.choose(option);\n return;\n }\n case 'Escape':\n if (!this.open) return;\n event.stopPropagation();\n this.closeList();\n return;\n case 'Tab':\n this.closeList();\n }\n }\n\n private optionId(index: number): string {\n return `${this.listId}-option-${index}`;\n }\n\n override render(): TemplateResult {\n const selected = this.selectedOption;\n const showClear = this.clearable && selected !== undefined && !this.disabled;\n\n return html`<div\n class=${classMap({ open: this.open, error: Boolean(this.error) })}\n @keydown=${this.onKeyDown}\n >\n <button\n part=\"trigger\"\n type=\"button\"\n class=\"trigger\"\n role=\"combobox\"\n aria-haspopup=\"listbox\"\n aria-expanded=${this.open ? 'true' : 'false'}\n aria-controls=${this.listId}\n aria-activedescendant=${\n this.open && this.activeIndex >= 0 ? this.optionId(this.activeIndex) : nothing\n }\n aria-label=${this.label || nothing}\n aria-invalid=${this.error ? 'true' : nothing}\n ?disabled=${this.disabled}\n @click=${this.toggleList}\n >\n <span class=${classMap({ value: true, placeholder: !selected })}>\n ${selected ? optionLabel(selected) : (this.placeholder ?? strings().select)}\n </span>\n <span class=\"icons\">\n ${\n showClear\n ? html`<span\n class=\"clear\"\n role=\"button\"\n tabindex=\"-1\"\n aria-label=${strings().clear}\n @click=${this.clear}\n >\n <kt-icon name=\"x\" size=\"18\"></kt-icon>\n </span>`\n : nothing\n }\n <span class=\"chevron\"><kt-icon name=\"chevron-down\" size=\"18\"></kt-icon></span>\n </span>\n </button>\n\n <ul\n part=\"popup\"\n id=${this.listId}\n class=${classMap({ popup: true, open: this.open })}\n role=\"listbox\"\n aria-label=${this.label || (this.placeholder ?? strings().select)}\n >\n ${\n this.options.length === 0\n ? html`<li class=\"empty\">${this.emptyText ?? strings().noOptions}</li>`\n : this.options.map(\n (option, index) =>\n html`<li\n part=\"option\"\n id=${this.optionId(index)}\n class=${classMap({\n option: true,\n selected: option.id === this.value,\n active: index === this.activeIndex,\n disabled: Boolean(option.disabled),\n })}\n role=\"option\"\n aria-selected=${option.id === this.value ? 'true' : 'false'}\n aria-disabled=${option.disabled ? 'true' : nothing}\n @click=${() => this.choose(option)}\n >\n ${optionLabel(option)}\n </li>`,\n )\n }\n </ul>\n </div>`;\n }\n}\n\ndefineElement('kt-select', KtSelect);\n\ndeclare global {\n interface HTMLElementTagNameMap {\n 'kt-select': KtSelect;\n }\n}\n"],"names":["KtSelect","KtElement","uniqueId","event","listboxStyles","css","attachFormInternals","changed","setFormValue","missing","setValidity","strings","state","options","option","selected","firstEnabledIndex","emit","nextEnabledIndex","lastEnabledIndex","index","showClear","html","classMap","nothing","optionLabel","__decorateClass","property","defineElement"],"mappings":"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"}
@@ -1,15 +1,16 @@
1
1
  import { css as m, nothing as i, html as l } from "lit";
2
2
  import { query as f, property as a } from "lit/decorators.js";
3
3
  import { classMap as u } from "lit/directives/class-map.js";
4
- import { live as b } from "lit/directives/live.js";
5
- import { K as c, d as g } from "../../../chunks/kt-element-B_jjQDhg.js";
4
+ import { live as g } from "lit/directives/live.js";
5
+ import { K as c, d as b } from "../../../chunks/kt-element-mdd5cXZX.js";
6
6
  import { e as p } from "../../../chunks/events-Bjl5Zmmq.js";
7
7
  import { a as y, s as v, b as x } from "../../../chunks/form-control-CxjBTt1c.js";
8
+ import { s as w } from "../../../chunks/index-fzPIgxe2.js";
8
9
  import "../../core/kt-icon/kt-icon.js";
9
- var w = Object.defineProperty, r = (n, e, o, $) => {
10
+ var $ = Object.defineProperty, r = (n, e, o, k) => {
10
11
  for (var s = void 0, h = n.length - 1, d; h >= 0; h--)
11
12
  (d = n[h]) && (s = d(e, o, s) || s);
12
- return s && w(e, o, s), s;
13
+ return s && $(e, o, s), s;
13
14
  };
14
15
  class t extends c {
15
16
  constructor() {
@@ -127,13 +128,13 @@ class t extends c {
127
128
  super.connectedCallback(), this.internals ??= y(this), this.defaultValue = this.value, v(this.internals, this.value);
128
129
  }
129
130
  willUpdate(e) {
130
- if (e.has("value") || e.has("required") || e.has("error")) {
131
+ if (e.has("value") || e.has("required") || e.has("error") || this.stringsChanged(e)) {
131
132
  v(this.internals, this.value);
132
133
  const o = this.required && this.value.length === 0;
133
134
  x(
134
135
  this.internals,
135
136
  { valueMissing: o, customError: !!this.error },
136
- this.error || (o ? "This field is required." : "")
137
+ this.error || (o ? w().required : "")
137
138
  );
138
139
  }
139
140
  }
@@ -175,7 +176,7 @@ class t extends c {
175
176
  aria-label=${this.label || i}
176
177
  aria-invalid=${this.error ? "true" : i}
177
178
  aria-describedby=${this.error ? "error-message" : i}
178
- .value=${b(this.value)}
179
+ .value=${g(this.value)}
179
180
  ?disabled=${this.disabled}
180
181
  ?readonly=${this.readonly}
181
182
  ?required=${this.required}
@@ -234,7 +235,7 @@ r([
234
235
  r([
235
236
  a({ type: String, reflect: !0 })
236
237
  ], t.prototype, "resize");
237
- g("kt-textarea", t);
238
+ b("kt-textarea", t);
238
239
  export {
239
240
  t as KtTextarea
240
241
  };
@@ -1 +1 @@
1
- {"version":3,"file":"kt-textarea.js","sources":["../../../../src/components/forms/kt-textarea/kt-textarea.ts"],"sourcesContent":["import { css, html, nothing, type PropertyValues, type TemplateResult } from 'lit';\nimport { property, query } from 'lit/decorators.js';\nimport { classMap } from 'lit/directives/class-map.js';\nimport { live } from 'lit/directives/live.js';\nimport { KtElement, defineElement } from '#internal/kt-element';\nimport { emit } from '#internal/events';\nimport {\n attachFormInternals,\n setFormValue,\n setValidity,\n type UsableInternals,\n} from '#internal/form-control';\nimport '../../core/kt-icon/kt-icon.js';\n\n/**\n * A multi-line text field, with the same borderless fill and outline states as\n * `<kt-input>`.\n *\n * A character counter appears whenever `maxlength` is set — the field tells\n * the user where the limit is before the browser silently stops accepting\n * keystrokes.\n *\n * @element kt-textarea\n *\n * @csspart base - The field container.\n * @csspart control - The native `<textarea>`.\n * @csspart counter - The character counter.\n *\n * @fires kt-input - On every keystroke. `detail: { value }`.\n * @fires kt-change - When the value is committed. `detail: { value }`.\n */\nexport class KtTextarea extends KtElement {\n static readonly formAssociated = true;\n\n static override styles = [\n KtElement.styles,\n css`\n :host {\n display: block;\n }\n\n .field {\n display: flex;\n align-items: flex-start;\n width: 100%;\n min-height: var(--button-height);\n background-color: var(--surface-field);\n border-radius: var(--radius-input);\n /* A resting hairline. A field is a fill on --surface-field, which is\n one ramp step from the page in dark and almost the same colour in\n light — so on a card or inside a modal it simply disappeared and\n read as a bare native control.\n\n A border rather than an outline, because the control inside fills\n the field exactly and a coincident outline is painted over by the\n native widget. A border insets the control by its own width, so it\n cannot be covered. box-sizing: border-box keeps the outer size.\n\n The hover and focus rings stay outlines on top of it, and the\n transparent resting outline is what they animate from: without it\n outline-color starts at the initial value, which resolves to the\n text colour, and hover flashed near-white before settling. */\n border: var(--border-width) solid var(--border-field);\n outline: var(--outline-width) solid transparent;\n transition: outline-color var(--duration-instant);\n }\n\n .field:hover {\n outline: var(--outline-width) solid var(--color-text-700);\n }\n .field:focus-within {\n outline: var(--outline-width) solid var(--color-primary-base);\n }\n\n .error,\n .error:hover,\n .error:focus-within {\n outline: var(--outline-width) solid var(--color-danger-base);\n }\n .error textarea {\n color: var(--color-danger-text);\n }\n\n .disabled {\n background-color: var(--color-dark-14);\n pointer-events: none;\n }\n .disabled textarea {\n color: var(--text-disabled);\n }\n\n textarea {\n width: 100%;\n min-height: calc(var(--button-height) - var(--gap-element) * 2);\n padding: var(--text-area-padding);\n color: var(--text-body);\n font: var(--font-input);\n background: transparent;\n border: none;\n outline: none;\n resize: none;\n }\n\n :host([resize='vertical']) textarea {\n resize: vertical;\n }\n\n textarea::placeholder {\n color: var(--text-muted);\n }\n\n .meta {\n display: flex;\n flex: none;\n flex-direction: column;\n align-items: center;\n gap: var(--gap-element);\n margin: 10px var(--button-padding-x) 0 0;\n }\n\n .counter {\n color: var(--color-text-700);\n font: var(--font-normal-small);\n font-variant-numeric: tabular-nums;\n white-space: nowrap;\n }\n\n .counter.at-limit {\n color: var(--color-danger-text);\n }\n\n .error-icon {\n display: flex;\n color: var(--color-danger-text);\n }\n `,\n ];\n\n @query('textarea')\n private control!: HTMLTextAreaElement;\n\n private internals: UsableInternals | null = null;\n private defaultValue = '';\n\n @property({ type: String })\n value = '';\n\n @property({ type: String })\n name = '';\n\n @property({ type: String })\n placeholder = '';\n\n @property({ type: Number })\n rows = 3;\n\n @property({ type: Number })\n maxlength?: number;\n\n @property({ type: Boolean, reflect: true })\n disabled = false;\n\n @property({ type: Boolean, reflect: true })\n readonly = false;\n\n @property({ type: Boolean, reflect: true })\n required = false;\n\n /** Error message. A non-empty value puts the field in its error state. */\n @property({ type: String, reflect: true })\n error = '';\n\n /** Accessible name, when no `<kt-label-input>` wraps the field. */\n @property({ type: String })\n label = '';\n\n /**\n * Whether the reader may drag the field taller.\n *\n * Off by default, as in the rest of Kanto: the grip is drawn by the operating\n * system, lands on the field's rounded corner and belongs to no design\n * system — and a field the layout sized is not usually the reader's to\n * resize. Turn it on where the content genuinely varies.\n */\n @property({ type: String, reflect: true })\n resize: 'vertical' | 'none' = 'none';\n\n override connectedCallback(): void {\n super.connectedCallback();\n this.internals ??= attachFormInternals(this);\n this.defaultValue = this.value;\n setFormValue(this.internals, this.value);\n }\n\n override willUpdate(changed: PropertyValues<this>): void {\n if (changed.has('value') || changed.has('required') || changed.has('error')) {\n setFormValue(this.internals, this.value);\n\n const missing = this.required && this.value.length === 0;\n setValidity(\n this.internals,\n { valueMissing: missing, customError: Boolean(this.error) },\n this.error || (missing ? 'This field is required.' : ''),\n );\n }\n }\n\n formResetCallback(): void {\n this.value = this.defaultValue;\n }\n\n formStateRestoreCallback(state: string): void {\n this.value = state;\n }\n\n override focus(options?: FocusOptions): void {\n this.control?.focus(options);\n }\n\n override blur(): void {\n this.control?.blur();\n }\n\n private onInput(event: Event): void {\n this.value = (event.target as HTMLTextAreaElement).value;\n emit(this, 'kt-input', { value: this.value });\n }\n\n private onChange(event: Event): void {\n event.stopPropagation();\n emit(this, 'kt-change', { value: this.value });\n }\n\n override render(): TemplateResult {\n const showCounter = this.maxlength !== undefined;\n const atLimit = this.maxlength !== undefined && this.value.length >= this.maxlength;\n\n return html`<div\n part=\"base\"\n class=${classMap({\n field: true,\n error: Boolean(this.error),\n disabled: this.disabled,\n })}\n >\n ${\n this.error\n ? html`<span id=\"error-message\" class=\"visually-hidden\">${this.error}</span>`\n : nothing\n }\n <textarea\n part=\"control\"\n name=${this.name || nothing}\n rows=${this.rows}\n maxlength=${this.maxlength ?? nothing}\n placeholder=${this.placeholder || nothing}\n aria-label=${this.label || nothing}\n aria-invalid=${this.error ? 'true' : nothing}\n aria-describedby=${this.error ? 'error-message' : nothing}\n .value=${live(this.value)}\n ?disabled=${this.disabled}\n ?readonly=${this.readonly}\n ?required=${this.required}\n @input=${this.onInput}\n @change=${this.onChange}\n ></textarea>\n\n ${\n this.error || showCounter\n ? html`<div class=\"meta\">\n ${\n this.error\n ? html`<span class=\"error-icon\" title=${this.error}>\n <kt-icon name=\"circle-alert\" size=\"18\" label=${this.error}></kt-icon>\n </span>`\n : nothing\n }\n ${\n showCounter\n ? html`<span\n part=\"counter\"\n class=${classMap({ counter: true, 'at-limit': atLimit })}\n aria-live=\"polite\"\n >\n ${this.value.length} / ${this.maxlength}\n </span>`\n : nothing\n }\n </div>`\n : nothing\n }\n </div>`;\n }\n}\n\ndefineElement('kt-textarea', KtTextarea);\n\ndeclare global {\n interface HTMLElementTagNameMap {\n 'kt-textarea': KtTextarea;\n }\n}\n"],"names":["KtTextarea","KtElement","css","attachFormInternals","setFormValue","changed","missing","setValidity","state","options","event","emit","showCounter","atLimit","html","classMap","nothing","live","__decorateClass","query","property","defineElement"],"mappings":"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"}
1
+ {"version":3,"file":"kt-textarea.js","sources":["../../../../src/components/forms/kt-textarea/kt-textarea.ts"],"sourcesContent":["import { css, html, nothing, type PropertyValues, type TemplateResult } from 'lit';\nimport { property, query } from 'lit/decorators.js';\nimport { classMap } from 'lit/directives/class-map.js';\nimport { live } from 'lit/directives/live.js';\nimport { KtElement, defineElement } from '#internal/kt-element';\nimport { emit } from '#internal/events';\nimport {\n attachFormInternals,\n setFormValue,\n setValidity,\n type UsableInternals,\n} from '#internal/form-control';\nimport { strings } from '#internal/strings';\nimport '../../core/kt-icon/kt-icon.js';\n\n/**\n * A multi-line text field, with the same borderless fill and outline states as\n * `<kt-input>`.\n *\n * A character counter appears whenever `maxlength` is set — the field tells\n * the user where the limit is before the browser silently stops accepting\n * keystrokes.\n *\n * @element kt-textarea\n *\n * @csspart base - The field container.\n * @csspart control - The native `<textarea>`.\n * @csspart counter - The character counter.\n *\n * @fires kt-input - On every keystroke. `detail: { value }`.\n * @fires kt-change - When the value is committed. `detail: { value }`.\n */\nexport class KtTextarea extends KtElement {\n static readonly formAssociated = true;\n\n static override styles = [\n KtElement.styles,\n css`\n :host {\n display: block;\n }\n\n .field {\n display: flex;\n align-items: flex-start;\n width: 100%;\n min-height: var(--button-height);\n background-color: var(--surface-field);\n border-radius: var(--radius-input);\n /* A resting hairline. A field is a fill on --surface-field, which is\n one ramp step from the page in dark and almost the same colour in\n light — so on a card or inside a modal it simply disappeared and\n read as a bare native control.\n\n A border rather than an outline, because the control inside fills\n the field exactly and a coincident outline is painted over by the\n native widget. A border insets the control by its own width, so it\n cannot be covered. box-sizing: border-box keeps the outer size.\n\n The hover and focus rings stay outlines on top of it, and the\n transparent resting outline is what they animate from: without it\n outline-color starts at the initial value, which resolves to the\n text colour, and hover flashed near-white before settling. */\n border: var(--border-width) solid var(--border-field);\n outline: var(--outline-width) solid transparent;\n transition: outline-color var(--duration-instant);\n }\n\n .field:hover {\n outline: var(--outline-width) solid var(--color-text-700);\n }\n .field:focus-within {\n outline: var(--outline-width) solid var(--color-primary-base);\n }\n\n .error,\n .error:hover,\n .error:focus-within {\n outline: var(--outline-width) solid var(--color-danger-base);\n }\n .error textarea {\n color: var(--color-danger-text);\n }\n\n .disabled {\n background-color: var(--color-dark-14);\n pointer-events: none;\n }\n .disabled textarea {\n color: var(--text-disabled);\n }\n\n textarea {\n width: 100%;\n min-height: calc(var(--button-height) - var(--gap-element) * 2);\n padding: var(--text-area-padding);\n color: var(--text-body);\n font: var(--font-input);\n background: transparent;\n border: none;\n outline: none;\n resize: none;\n }\n\n :host([resize='vertical']) textarea {\n resize: vertical;\n }\n\n textarea::placeholder {\n color: var(--text-muted);\n }\n\n .meta {\n display: flex;\n flex: none;\n flex-direction: column;\n align-items: center;\n gap: var(--gap-element);\n margin: 10px var(--button-padding-x) 0 0;\n }\n\n .counter {\n color: var(--color-text-700);\n font: var(--font-normal-small);\n font-variant-numeric: tabular-nums;\n white-space: nowrap;\n }\n\n .counter.at-limit {\n color: var(--color-danger-text);\n }\n\n .error-icon {\n display: flex;\n color: var(--color-danger-text);\n }\n `,\n ];\n\n @query('textarea')\n private control!: HTMLTextAreaElement;\n\n private internals: UsableInternals | null = null;\n private defaultValue = '';\n\n @property({ type: String })\n value = '';\n\n @property({ type: String })\n name = '';\n\n @property({ type: String })\n placeholder = '';\n\n @property({ type: Number })\n rows = 3;\n\n @property({ type: Number })\n maxlength?: number;\n\n @property({ type: Boolean, reflect: true })\n disabled = false;\n\n @property({ type: Boolean, reflect: true })\n readonly = false;\n\n @property({ type: Boolean, reflect: true })\n required = false;\n\n /** Error message. A non-empty value puts the field in its error state. */\n @property({ type: String, reflect: true })\n error = '';\n\n /** Accessible name, when no `<kt-label-input>` wraps the field. */\n @property({ type: String })\n label = '';\n\n /**\n * Whether the reader may drag the field taller.\n *\n * Off by default, as in the rest of Kanto: the grip is drawn by the operating\n * system, lands on the field's rounded corner and belongs to no design\n * system — and a field the layout sized is not usually the reader's to\n * resize. Turn it on where the content genuinely varies.\n */\n @property({ type: String, reflect: true })\n resize: 'vertical' | 'none' = 'none';\n\n override connectedCallback(): void {\n super.connectedCallback();\n this.internals ??= attachFormInternals(this);\n this.defaultValue = this.value;\n setFormValue(this.internals, this.value);\n }\n\n override willUpdate(changed: PropertyValues<this>): void {\n if (\n changed.has('value') ||\n changed.has('required') ||\n changed.has('error') ||\n this.stringsChanged(changed)\n ) {\n setFormValue(this.internals, this.value);\n\n const missing = this.required && this.value.length === 0;\n setValidity(\n this.internals,\n { valueMissing: missing, customError: Boolean(this.error) },\n this.error || (missing ? strings().required : ''),\n );\n }\n }\n\n formResetCallback(): void {\n this.value = this.defaultValue;\n }\n\n formStateRestoreCallback(state: string): void {\n this.value = state;\n }\n\n override focus(options?: FocusOptions): void {\n this.control?.focus(options);\n }\n\n override blur(): void {\n this.control?.blur();\n }\n\n private onInput(event: Event): void {\n this.value = (event.target as HTMLTextAreaElement).value;\n emit(this, 'kt-input', { value: this.value });\n }\n\n private onChange(event: Event): void {\n event.stopPropagation();\n emit(this, 'kt-change', { value: this.value });\n }\n\n override render(): TemplateResult {\n const showCounter = this.maxlength !== undefined;\n const atLimit = this.maxlength !== undefined && this.value.length >= this.maxlength;\n\n return html`<div\n part=\"base\"\n class=${classMap({\n field: true,\n error: Boolean(this.error),\n disabled: this.disabled,\n })}\n >\n ${\n this.error\n ? html`<span id=\"error-message\" class=\"visually-hidden\">${this.error}</span>`\n : nothing\n }\n <textarea\n part=\"control\"\n name=${this.name || nothing}\n rows=${this.rows}\n maxlength=${this.maxlength ?? nothing}\n placeholder=${this.placeholder || nothing}\n aria-label=${this.label || nothing}\n aria-invalid=${this.error ? 'true' : nothing}\n aria-describedby=${this.error ? 'error-message' : nothing}\n .value=${live(this.value)}\n ?disabled=${this.disabled}\n ?readonly=${this.readonly}\n ?required=${this.required}\n @input=${this.onInput}\n @change=${this.onChange}\n ></textarea>\n\n ${\n this.error || showCounter\n ? html`<div class=\"meta\">\n ${\n this.error\n ? html`<span class=\"error-icon\" title=${this.error}>\n <kt-icon name=\"circle-alert\" size=\"18\" label=${this.error}></kt-icon>\n </span>`\n : nothing\n }\n ${\n showCounter\n ? html`<span\n part=\"counter\"\n class=${classMap({ counter: true, 'at-limit': atLimit })}\n aria-live=\"polite\"\n >\n ${this.value.length} / ${this.maxlength}\n </span>`\n : nothing\n }\n </div>`\n : nothing\n }\n </div>`;\n }\n}\n\ndefineElement('kt-textarea', KtTextarea);\n\ndeclare global {\n interface HTMLElementTagNameMap {\n 'kt-textarea': KtTextarea;\n }\n}\n"],"names":["KtTextarea","KtElement","css","attachFormInternals","setFormValue","changed","missing","setValidity","strings","state","options","event","emit","showCounter","atLimit","html","classMap","nothing","live","__decorateClass","query","property","defineElement"],"mappings":"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"}
@@ -1,6 +1,6 @@
1
1
  import { css as d, nothing as h, html as u } from "lit";
2
2
  import { property as r } from "lit/decorators.js";
3
- import { K as n, d as b } from "../../../chunks/kt-element-B_jjQDhg.js";
3
+ import { K as n, d as b } from "../../../chunks/kt-element-mdd5cXZX.js";
4
4
  import { e as p } from "../../../chunks/events-Bjl5Zmmq.js";
5
5
  import { a as m, s as g } from "../../../chunks/form-control-CxjBTt1c.js";
6
6
  var k = Object.defineProperty, s = (i, t, l, v) => {
@@ -34,7 +34,7 @@ export declare class KtBreadcrumb extends KtElement {
34
34
  /** The trail, root first. The last entry is the current page. */
35
35
  items: readonly KtBreadcrumbItem[];
36
36
  /** Accessible name for the navigation landmark. */
37
- label: string;
37
+ label: string | undefined;
38
38
  private onSelect;
39
39
  render(): TemplateResult;
40
40
  }
@@ -1,16 +1,17 @@
1
1
  import { css as d, nothing as f, html as s } from "lit";
2
2
  import { property as c } from "lit/decorators.js";
3
- import { K as p, d as u } from "../../../chunks/kt-element-B_jjQDhg.js";
3
+ import { K as p, d as u } from "../../../chunks/kt-element-mdd5cXZX.js";
4
4
  import { e as h } from "../../../chunks/events-Bjl5Zmmq.js";
5
+ import { s as b } from "../../../chunks/index-fzPIgxe2.js";
5
6
  import "../../core/kt-icon/kt-icon.js";
6
- var b = Object.defineProperty, m = (o, t, e, a) => {
7
+ var v = Object.defineProperty, m = (o, t, e, a) => {
7
8
  for (var r = void 0, i = o.length - 1, l; i >= 0; i--)
8
9
  (l = o[i]) && (r = l(t, e, r) || r);
9
- return r && b(t, e, r), r;
10
+ return r && v(t, e, r), r;
10
11
  };
11
12
  class n extends p {
12
13
  constructor() {
13
- super(...arguments), this.items = [], this.label = "Breadcrumb";
14
+ super(...arguments), this.items = [], this.label = void 0;
14
15
  }
15
16
  static {
16
17
  this.styles = [
@@ -63,7 +64,7 @@ class n extends p {
63
64
  }
64
65
  render() {
65
66
  const t = this.items.length - 1;
66
- return s`<nav part="nav" aria-label=${this.label}>
67
+ return s`<nav part="nav" aria-label=${this.label ?? b().breadcrumb}>
67
68
  ${this.items.map(
68
69
  (e, a) => a === t ? s`<span part="item" class="item current" aria-current="page">${e.label}</span>` : s`<a
69
70
  part="item"
@@ -1 +1 @@
1
- {"version":3,"file":"kt-breadcrumb.js","sources":["../../../../src/components/navigation/kt-breadcrumb/kt-breadcrumb.ts"],"sourcesContent":["import { css, html, nothing, type TemplateResult } from 'lit';\nimport { property } from 'lit/decorators.js';\nimport { KtElement, defineElement } from '#internal/kt-element';\nimport { emit } from '#internal/events';\nimport '../../core/kt-icon/kt-icon.js';\n\nexport interface KtBreadcrumbItem {\n readonly label: string;\n readonly href?: string;\n}\n\n/**\n * A trail showing where the current page sits.\n *\n * The last entry is the current page: rendered as text, not a link, and marked\n * `aria-current=\"page\"`. A breadcrumb whose final item links to the page you\n * are already on is a dead control.\n *\n * @element kt-breadcrumb\n *\n * @csspart nav - The `<nav>`.\n * @csspart item - A trail entry.\n *\n * @fires kt-navigate - An entry was activated. `detail: { item, index }`.\n * Cancel it to keep the browser from following the href.\n *\n * @example\n * ```js\n * trail.items = [\n * { label: 'Home', href: '/' },\n * { label: 'Entities', href: '/entities' },\n * { label: 'Entity 4812' },\n * ];\n * ```\n */\nexport class KtBreadcrumb extends KtElement {\n static override styles = [\n KtElement.styles,\n css`\n :host {\n display: block;\n }\n\n nav {\n display: flex;\n flex-wrap: wrap;\n align-items: center;\n gap: 6px;\n }\n\n .item {\n padding: 2px 6px;\n color: var(--text-muted);\n font: var(--font-normal-regular);\n border-radius: 6px;\n text-decoration: none;\n }\n\n a.item:hover {\n color: var(--text-body);\n background: var(--color-dark-18);\n text-decoration: none;\n }\n\n a.item:focus-visible {\n outline: var(--outline-width) solid var(--color-primary-base);\n outline-offset: 1px;\n }\n\n .current {\n color: var(--text-body);\n font: var(--font-normal-medium);\n }\n\n .separator {\n display: inline-flex;\n color: var(--color-text-600);\n }\n `,\n ];\n\n /** The trail, root first. The last entry is the current page. */\n @property({ attribute: false })\n items: readonly KtBreadcrumbItem[] = [];\n\n /** Accessible name for the navigation landmark. */\n @property({ type: String })\n label = 'Breadcrumb';\n\n private onSelect(event: MouseEvent, item: KtBreadcrumbItem, index: number): void {\n // Let modified clicks through: they open a new tab, which is the user\n // asking the browser for something we should not intercept.\n if (event.metaKey || event.ctrlKey || event.shiftKey || event.button !== 0) return;\n\n const proceed = emit(this, 'kt-navigate', { item, index });\n if (!proceed.defaultPrevented) return;\n event.preventDefault();\n }\n\n override render(): TemplateResult {\n const lastIndex = this.items.length - 1;\n\n return html`<nav part=\"nav\" aria-label=${this.label}>\n ${this.items.map((item, index) =>\n index === lastIndex\n ? html`<span part=\"item\" class=\"item current\" aria-current=\"page\">${item.label}</span>`\n : html`<a\n part=\"item\"\n class=\"item\"\n href=${item.href ?? '#'}\n @click=${(event: MouseEvent) => this.onSelect(event, item, index)}\n >${item.label}</a\n >\n <span class=\"separator\" aria-hidden=\"true\">\n <kt-icon name=\"chevron-right\" size=\"14\"></kt-icon>\n </span>`,\n )}\n ${this.items.length === 0 ? nothing : ''}\n </nav>`;\n }\n}\n\ndefineElement('kt-breadcrumb', KtBreadcrumb);\n\ndeclare global {\n interface HTMLElementTagNameMap {\n 'kt-breadcrumb': KtBreadcrumb;\n }\n}\n"],"names":["KtBreadcrumb","KtElement","css","event","item","index","emit","lastIndex","html","nothing","__decorateClass","property","defineElement"],"mappings":";;;;;;;;;;AAmCO,MAAMA,UAAqBC,EAAU;AAAA,EAArC,cAAA;AAAA,UAAA,GAAA,SAAA,GAgDL,KAAA,QAAqC,CAAA,GAIrC,KAAA,QAAQ;AAAA,EAAA;AAAA,EAnDR,OAAA;AAAA,SAAgB,SAAS;AAAA,MACvBA,EAAU;AAAA,MACVC;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,IAAA;AAAA,EAyCF;AAAA,EAUQ,SAASC,GAAmBC,GAAwBC,GAAqB;AAM/E,IAHIF,EAAM,WAAWA,EAAM,WAAWA,EAAM,YAAYA,EAAM,WAAW,KAGrE,CADYG,EAAK,MAAM,eAAe,EAAE,MAAAF,GAAM,OAAAC,GAAO,EAC5C,oBACbF,EAAM,eAAA;AAAA,EACR;AAAA,EAES,SAAyB;AAChC,UAAMI,IAAY,KAAK,MAAM,SAAS;AAEtC,WAAOC,+BAAkC,KAAK,KAAK;AAAA,QAC/C,KAAK,MAAM;AAAA,MAAI,CAACJ,GAAMC,MACtBA,MAAUE,IACNC,+DAAkEJ,EAAK,KAAK,YAC5EI;AAAA;AAAA;AAAA,uBAGWJ,EAAK,QAAQ,GAAG;AAAA,yBACd,CAACD,MAAsB,KAAK,SAASA,GAAOC,GAAMC,CAAK,CAAC;AAAA,mBAC9DD,EAAK,KAAK;AAAA;AAAA;AAAA;AAAA;AAAA,IAAA,CAKtB;AAAA,QACC,KAAK,MAAM,WAAW,IAAIK,IAAU,EAAE;AAAA;AAAA,EAE5C;AACF;AArCEC,EAAA;AAAA,EADCC,EAAS,EAAE,WAAW,GAAA,CAAO;AAAA,GA/CnBX,EAgDX,WAAA,OAAA;AAIAU,EAAA;AAAA,EADCC,EAAS,EAAE,MAAM,OAAA,CAAQ;AAAA,GAnDfX,EAoDX,WAAA,OAAA;AAmCFY,EAAc,iBAAiBZ,CAAY;"}
1
+ {"version":3,"file":"kt-breadcrumb.js","sources":["../../../../src/components/navigation/kt-breadcrumb/kt-breadcrumb.ts"],"sourcesContent":["import { css, html, nothing, type TemplateResult } from 'lit';\nimport { property } from 'lit/decorators.js';\nimport { KtElement, defineElement } from '#internal/kt-element';\nimport { emit } from '#internal/events';\nimport { strings } from '#internal/strings';\nimport '../../core/kt-icon/kt-icon.js';\n\nexport interface KtBreadcrumbItem {\n readonly label: string;\n readonly href?: string;\n}\n\n/**\n * A trail showing where the current page sits.\n *\n * The last entry is the current page: rendered as text, not a link, and marked\n * `aria-current=\"page\"`. A breadcrumb whose final item links to the page you\n * are already on is a dead control.\n *\n * @element kt-breadcrumb\n *\n * @csspart nav - The `<nav>`.\n * @csspart item - A trail entry.\n *\n * @fires kt-navigate - An entry was activated. `detail: { item, index }`.\n * Cancel it to keep the browser from following the href.\n *\n * @example\n * ```js\n * trail.items = [\n * { label: 'Home', href: '/' },\n * { label: 'Entities', href: '/entities' },\n * { label: 'Entity 4812' },\n * ];\n * ```\n */\nexport class KtBreadcrumb extends KtElement {\n static override styles = [\n KtElement.styles,\n css`\n :host {\n display: block;\n }\n\n nav {\n display: flex;\n flex-wrap: wrap;\n align-items: center;\n gap: 6px;\n }\n\n .item {\n padding: 2px 6px;\n color: var(--text-muted);\n font: var(--font-normal-regular);\n border-radius: 6px;\n text-decoration: none;\n }\n\n a.item:hover {\n color: var(--text-body);\n background: var(--color-dark-18);\n text-decoration: none;\n }\n\n a.item:focus-visible {\n outline: var(--outline-width) solid var(--color-primary-base);\n outline-offset: 1px;\n }\n\n .current {\n color: var(--text-body);\n font: var(--font-normal-medium);\n }\n\n .separator {\n display: inline-flex;\n color: var(--color-text-600);\n }\n `,\n ];\n\n /** The trail, root first. The last entry is the current page. */\n @property({ attribute: false })\n items: readonly KtBreadcrumbItem[] = [];\n\n /** Accessible name for the navigation landmark. */\n @property({ type: String })\n label: string | undefined = undefined;\n\n private onSelect(event: MouseEvent, item: KtBreadcrumbItem, index: number): void {\n // Let modified clicks through: they open a new tab, which is the user\n // asking the browser for something we should not intercept.\n if (event.metaKey || event.ctrlKey || event.shiftKey || event.button !== 0) return;\n\n const proceed = emit(this, 'kt-navigate', { item, index });\n if (!proceed.defaultPrevented) return;\n event.preventDefault();\n }\n\n override render(): TemplateResult {\n const lastIndex = this.items.length - 1;\n\n return html`<nav part=\"nav\" aria-label=${this.label ?? strings().breadcrumb}>\n ${this.items.map((item, index) =>\n index === lastIndex\n ? html`<span part=\"item\" class=\"item current\" aria-current=\"page\">${item.label}</span>`\n : html`<a\n part=\"item\"\n class=\"item\"\n href=${item.href ?? '#'}\n @click=${(event: MouseEvent) => this.onSelect(event, item, index)}\n >${item.label}</a\n >\n <span class=\"separator\" aria-hidden=\"true\">\n <kt-icon name=\"chevron-right\" size=\"14\"></kt-icon>\n </span>`,\n )}\n ${this.items.length === 0 ? nothing : ''}\n </nav>`;\n }\n}\n\ndefineElement('kt-breadcrumb', KtBreadcrumb);\n\ndeclare global {\n interface HTMLElementTagNameMap {\n 'kt-breadcrumb': KtBreadcrumb;\n }\n}\n"],"names":["KtBreadcrumb","KtElement","css","event","item","index","emit","lastIndex","html","strings","nothing","__decorateClass","property","defineElement"],"mappings":";;;;;;;;;;;AAoCO,MAAMA,UAAqBC,EAAU;AAAA,EAArC,cAAA;AAAA,UAAA,GAAA,SAAA,GAgDL,KAAA,QAAqC,CAAA,GAIrC,KAAA,QAA4B;AAAA,EAAA;AAAA,EAnD5B,OAAA;AAAA,SAAgB,SAAS;AAAA,MACvBA,EAAU;AAAA,MACVC;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,IAAA;AAAA,EAyCF;AAAA,EAUQ,SAASC,GAAmBC,GAAwBC,GAAqB;AAM/E,IAHIF,EAAM,WAAWA,EAAM,WAAWA,EAAM,YAAYA,EAAM,WAAW,KAGrE,CADYG,EAAK,MAAM,eAAe,EAAE,MAAAF,GAAM,OAAAC,GAAO,EAC5C,oBACbF,EAAM,eAAA;AAAA,EACR;AAAA,EAES,SAAyB;AAChC,UAAMI,IAAY,KAAK,MAAM,SAAS;AAEtC,WAAOC,+BAAkC,KAAK,SAASC,EAAA,EAAU,UAAU;AAAA,QACvE,KAAK,MAAM;AAAA,MAAI,CAACL,GAAMC,MACtBA,MAAUE,IACNC,+DAAkEJ,EAAK,KAAK,YAC5EI;AAAA;AAAA;AAAA,uBAGWJ,EAAK,QAAQ,GAAG;AAAA,yBACd,CAACD,MAAsB,KAAK,SAASA,GAAOC,GAAMC,CAAK,CAAC;AAAA,mBAC9DD,EAAK,KAAK;AAAA;AAAA;AAAA;AAAA;AAAA,IAAA,CAKtB;AAAA,QACC,KAAK,MAAM,WAAW,IAAIM,IAAU,EAAE;AAAA;AAAA,EAE5C;AACF;AArCEC,EAAA;AAAA,EADCC,EAAS,EAAE,WAAW,GAAA,CAAO;AAAA,GA/CnBZ,EAgDX,WAAA,OAAA;AAIAW,EAAA;AAAA,EADCC,EAAS,EAAE,MAAM,OAAA,CAAQ;AAAA,GAnDfZ,EAoDX,WAAA,OAAA;AAmCFa,EAAc,iBAAiBb,CAAY;"}
@@ -1,12 +1,13 @@
1
- import { css as h, nothing as c, html as u } from "lit";
2
- import { state as m, property as n } from "lit/decorators.js";
3
- import { K as d, d as b } from "../../../chunks/kt-element-B_jjQDhg.js";
1
+ import { css as c, nothing as u, html as m } from "lit";
2
+ import { state as b, property as n } from "lit/decorators.js";
3
+ import { K as d, d as f } from "../../../chunks/kt-element-mdd5cXZX.js";
4
4
  import { e as p } from "../../../chunks/events-Bjl5Zmmq.js";
5
+ import { s as h } from "../../../chunks/index-fzPIgxe2.js";
5
6
  import "../../core/kt-button/kt-button.js";
6
- var f = Object.defineProperty, a = (r, o, s, g) => {
7
+ var g = Object.defineProperty, a = (r, o, s, v) => {
7
8
  for (var e = void 0, i = r.length - 1, l; i >= 0; i--)
8
9
  (l = r[i]) && (e = l(o, s, e) || e);
9
- return e && f(o, s, e), e;
10
+ return e && g(o, s, e), e;
10
11
  };
11
12
  class t extends d {
12
13
  constructor() {
@@ -15,7 +16,7 @@ class t extends d {
15
16
  static {
16
17
  this.styles = [
17
18
  d.styles,
18
- h`
19
+ c`
19
20
  :host {
20
21
  display: block;
21
22
  --kt-header-height: 64px;
@@ -146,7 +147,7 @@ class t extends d {
146
147
  this.menuOpen = !this.menuOpen, p(this, "kt-menu-toggle", { open: this.menuOpen });
147
148
  }
148
149
  render() {
149
- return u`<header part="base" role="banner" aria-label=${this.label || c}>
150
+ return m`<header part="base" role="banner" aria-label=${this.label || u}>
150
151
  <div part="bar" class="bar">
151
152
  <div class="brand"><slot name="brand"></slot></div>
152
153
 
@@ -159,7 +160,7 @@ class t extends d {
159
160
  variant="secondary-no-bg"
160
161
  size="small"
161
162
  icon=${this.menuOpen ? "x" : "menu"}
162
- label=${this.menuOpen ? "Close menu" : "Open menu"}
163
+ label=${this.menuOpen ? h().closeMenu : h().openMenu}
163
164
  aria-expanded=${this.menuOpen ? "true" : "false"}
164
165
  @click=${this.toggleMenu}
165
166
  ></kt-button>
@@ -174,7 +175,7 @@ class t extends d {
174
175
  }
175
176
  }
176
177
  a([
177
- m()
178
+ b()
178
179
  ], t.prototype, "menuOpen");
179
180
  a([
180
181
  n({ type: Boolean, reflect: !0 })
@@ -188,7 +189,7 @@ a([
188
189
  a([
189
190
  n({ type: String })
190
191
  ], t.prototype, "label");
191
- b("kt-header", t);
192
+ f("kt-header", t);
192
193
  export {
193
194
  t as KtHeader
194
195
  };
@@ -1 +1 @@
1
- {"version":3,"file":"kt-header.js","sources":["../../../../src/components/navigation/kt-header/kt-header.ts"],"sourcesContent":["import { css, html, nothing, type TemplateResult } from 'lit';\nimport { property, state } from 'lit/decorators.js';\nimport { KtElement, defineElement } from '#internal/kt-element';\nimport { emit } from '#internal/events';\nimport '../../core/kt-button/kt-button.js';\n\n/**\n * The application header: a banner landmark holding the brand, the primary\n * navigation and a row of actions.\n *\n * Below `--kt-header-breakpoint` (900px by default) the navigation collapses\n * behind a menu button and reappears as a panel under the bar. That threshold\n * is a token rather than a hard-coded media query, because how much navigation\n * fits depends on how much navigation you put in.\n *\n * @element kt-header\n *\n * @slot brand - Logo or wordmark, at the start.\n * @slot - Primary navigation, in the middle.\n * @slot actions - Buttons and links, at the end. Stays visible on mobile.\n * @slot menu - What the menu button reveals below the breakpoint. Separate\n * from the default slot because a node can only be assigned to one slot; put\n * a compact copy of the navigation here.\n * @slot bottom - A second row under the bar — sub-navigation, a breadcrumb.\n *\n * @csspart base - The `<header>`.\n * @csspart bar - The main row.\n * @csspart bottom - The second row.\n *\n * The bar is a three-column grid whose outer columns are equal, so the\n * navigation is centred in the bar rather than in whatever the brand and the\n * actions left over. Set `nav-align=\"start\"` to butt it against the brand\n * instead.\n *\n * @cssproperty --kt-header-breakpoint - Where the navigation collapses. 900px.\n * @cssproperty --kt-header-height - Height of the main row. 64px.\n *\n * @fires kt-menu-toggle - The mobile menu opened or closed. `detail: { open }`.\n *\n * @example\n * ```html\n * <kt-header sticky>\n * <a slot=\"brand\" href=\"/\">KANTO</a>\n * <nav><a href=\"/docs\">Docs</a><a href=\"/components\">Components</a></nav>\n * <kt-button slot=\"actions\" size=\"small\" icon=\"github\" label=\"GitHub\"></kt-button>\n * </kt-header>\n * ```\n */\nexport class KtHeader extends KtElement {\n static override styles = [\n KtElement.styles,\n css`\n :host {\n display: block;\n --kt-header-height: 64px;\n --kt-header-breakpoint: 900px;\n }\n\n :host([sticky]) {\n position: sticky;\n top: 0;\n z-index: var(--z-dropdown);\n }\n\n header {\n background-color: var(--surface-page);\n }\n\n /* Translucent only where the browser can actually blur; an unblurred\n semi-transparent bar is just hard to read. */\n @supports (backdrop-filter: blur(1px)) {\n :host([sticky]) header {\n background-color: color-mix(in srgb, var(--surface-page) 80%, transparent);\n backdrop-filter: blur(12px);\n }\n }\n\n :host([bordered]) header {\n border-bottom: var(--border-width) solid var(--border-subtle);\n }\n\n /* Three columns rather than a flex row, and the outer two share what is\n left equally: with flex:1 on the middle, the navigation is centred in\n the leftover space, so it sits off-centre by half the difference\n between the brand and the actions — which is exactly how far off it\n looked. Equal outer columns centre it in the bar itself. */\n .bar {\n display: grid;\n grid-template-columns: minmax(0, 1fr) auto minmax(0, 1fr);\n align-items: center;\n gap: var(--gap-card);\n min-height: var(--kt-header-height);\n padding: 0 var(--padding-card);\n }\n\n :host([nav-align='start']) .bar {\n grid-template-columns: auto minmax(0, 1fr) auto;\n }\n\n .brand {\n display: flex;\n align-items: center;\n gap: var(--gap-button);\n color: var(--text-body);\n font: var(--font-title-h6);\n line-height: 1;\n }\n\n /* A wordmark is capitals, and capitals use none of a font's descent — so\n centring the *line box* parks the letters half a descent high, which is\n about 1.5px at 18px in Manrope and reads as a misalignment rather than\n as a font. Trimming the box to the cap height and the baseline centres\n what the eye actually sees. */\n @supports (text-box: trim-both cap alphabetic) {\n .brand ::slotted(*) {\n text-box: trim-both cap alphabetic;\n }\n }\n\n .nav {\n display: flex;\n align-items: center;\n justify-content: center;\n min-width: 0;\n }\n\n :host([nav-align='start']) .nav {\n justify-content: flex-start;\n }\n\n .actions {\n display: flex;\n align-items: center;\n justify-content: flex-end;\n gap: var(--gap-button);\n }\n\n .bottom {\n padding: 0 var(--padding-card);\n }\n\n /* Hidden above the breakpoint; the container query cannot help here\n because the header spans the viewport by definition. */\n .menu-button {\n display: none;\n flex: none;\n }\n\n .panel {\n display: none;\n }\n\n @media (max-width: 899px) {\n .menu-button {\n display: inline-flex;\n }\n\n .nav {\n display: none;\n }\n\n .panel.open {\n display: block;\n padding: 0 var(--padding-card) var(--padding-form);\n border-top: var(--border-width) solid var(--border-subtle);\n }\n }\n `,\n ];\n\n @state()\n private menuOpen = false;\n\n /** Pins the header to the top of the viewport. */\n @property({ type: Boolean, reflect: true })\n sticky = false;\n\n /** Where the navigation sits: centred in the bar, or against the brand. */\n @property({ type: String, reflect: true, attribute: 'nav-align' })\n navAlign: 'center' | 'start' = 'center';\n\n @property({ type: Boolean, reflect: true })\n bordered = true;\n\n /** Accessible name for the banner, when a page has more than one. */\n @property({ type: String })\n label = '';\n\n /** Whether the collapsed navigation panel is showing. */\n get isMenuOpen(): boolean {\n return this.menuOpen;\n }\n\n /** Closes the collapsed navigation — call it after routing. */\n closeMenu(): void {\n if (!this.menuOpen) return;\n this.menuOpen = false;\n emit(this, 'kt-menu-toggle', { open: false });\n }\n\n private toggleMenu(): void {\n this.menuOpen = !this.menuOpen;\n emit(this, 'kt-menu-toggle', { open: this.menuOpen });\n }\n\n override render(): TemplateResult {\n return html`<header part=\"base\" role=\"banner\" aria-label=${this.label || nothing}>\n <div part=\"bar\" class=\"bar\">\n <div class=\"brand\"><slot name=\"brand\"></slot></div>\n\n <div class=\"nav\"><slot></slot></div>\n\n <div class=\"actions\"><slot name=\"actions\"></slot></div>\n\n <kt-button\n class=\"menu-button\"\n variant=\"secondary-no-bg\"\n size=\"small\"\n icon=${this.menuOpen ? 'x' : 'menu'}\n label=${this.menuOpen ? 'Close menu' : 'Open menu'}\n aria-expanded=${this.menuOpen ? 'true' : 'false'}\n @click=${this.toggleMenu}\n ></kt-button>\n </div>\n\n <div class=\"panel ${this.menuOpen ? 'open' : ''}\">\n <slot name=\"menu\"></slot>\n </div>\n\n <div part=\"bottom\" class=\"bottom\"><slot name=\"bottom\"></slot></div>\n </header>`;\n }\n}\n\ndefineElement('kt-header', KtHeader);\n\ndeclare global {\n interface HTMLElementTagNameMap {\n 'kt-header': KtHeader;\n }\n}\n"],"names":["KtHeader","KtElement","css","emit","html","nothing","__decorateClass","state","property","defineElement"],"mappings":";;;;;;;;;;AAgDO,MAAMA,UAAiBC,EAAU;AAAA,EAAjC,cAAA;AAAA,UAAA,GAAA,SAAA,GA2HL,KAAQ,WAAW,IAInB,KAAA,SAAS,IAIT,KAAA,WAA+B,UAG/B,KAAA,WAAW,IAIX,KAAA,QAAQ;AAAA,EAAA;AAAA,EAzIR,OAAA;AAAA,SAAgB,SAAS;AAAA,MACvBA,EAAU;AAAA,MACVC;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,IAAA;AAAA,EAqHF;AAAA;AAAA,EAqBA,IAAI,aAAsB;AACxB,WAAO,KAAK;AAAA,EACd;AAAA;AAAA,EAGA,YAAkB;AAChB,IAAK,KAAK,aACV,KAAK,WAAW,IAChBC,EAAK,MAAM,kBAAkB,EAAE,MAAM,IAAO;AAAA,EAC9C;AAAA,EAEQ,aAAmB;AACzB,SAAK,WAAW,CAAC,KAAK,UACtBA,EAAK,MAAM,kBAAkB,EAAE,MAAM,KAAK,UAAU;AAAA,EACtD;AAAA,EAES,SAAyB;AAChC,WAAOC,iDAAoD,KAAK,SAASC,CAAO;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,iBAYnE,KAAK,WAAW,MAAM,MAAM;AAAA,kBAC3B,KAAK,WAAW,eAAe,WAAW;AAAA,0BAClC,KAAK,WAAW,SAAS,OAAO;AAAA,mBACvC,KAAK,UAAU;AAAA;AAAA;AAAA;AAAA,0BAIR,KAAK,WAAW,SAAS,EAAE;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAMnD;AACF;AA7DUC,EAAA;AAAA,EADPC,EAAA;AAAM,GA1HIP,EA2HH,WAAA,UAAA;AAIRM,EAAA;AAAA,EADCE,EAAS,EAAE,MAAM,SAAS,SAAS,IAAM;AAAA,GA9H/BR,EA+HX,WAAA,QAAA;AAIAM,EAAA;AAAA,EADCE,EAAS,EAAE,MAAM,QAAQ,SAAS,IAAM,WAAW,aAAa;AAAA,GAlItDR,EAmIX,WAAA,UAAA;AAGAM,EAAA;AAAA,EADCE,EAAS,EAAE,MAAM,SAAS,SAAS,IAAM;AAAA,GArI/BR,EAsIX,WAAA,UAAA;AAIAM,EAAA;AAAA,EADCE,EAAS,EAAE,MAAM,OAAA,CAAQ;AAAA,GAzIfR,EA0IX,WAAA,OAAA;AAgDFS,EAAc,aAAaT,CAAQ;"}
1
+ {"version":3,"file":"kt-header.js","sources":["../../../../src/components/navigation/kt-header/kt-header.ts"],"sourcesContent":["import { css, html, nothing, type TemplateResult } from 'lit';\nimport { property, state } from 'lit/decorators.js';\nimport { KtElement, defineElement } from '#internal/kt-element';\nimport { emit } from '#internal/events';\nimport { strings } from '#internal/strings';\nimport '../../core/kt-button/kt-button.js';\n\n/**\n * The application header: a banner landmark holding the brand, the primary\n * navigation and a row of actions.\n *\n * Below `--kt-header-breakpoint` (900px by default) the navigation collapses\n * behind a menu button and reappears as a panel under the bar. That threshold\n * is a token rather than a hard-coded media query, because how much navigation\n * fits depends on how much navigation you put in.\n *\n * @element kt-header\n *\n * @slot brand - Logo or wordmark, at the start.\n * @slot - Primary navigation, in the middle.\n * @slot actions - Buttons and links, at the end. Stays visible on mobile.\n * @slot menu - What the menu button reveals below the breakpoint. Separate\n * from the default slot because a node can only be assigned to one slot; put\n * a compact copy of the navigation here.\n * @slot bottom - A second row under the bar — sub-navigation, a breadcrumb.\n *\n * @csspart base - The `<header>`.\n * @csspart bar - The main row.\n * @csspart bottom - The second row.\n *\n * The bar is a three-column grid whose outer columns are equal, so the\n * navigation is centred in the bar rather than in whatever the brand and the\n * actions left over. Set `nav-align=\"start\"` to butt it against the brand\n * instead.\n *\n * @cssproperty --kt-header-breakpoint - Where the navigation collapses. 900px.\n * @cssproperty --kt-header-height - Height of the main row. 64px.\n *\n * @fires kt-menu-toggle - The mobile menu opened or closed. `detail: { open }`.\n *\n * @example\n * ```html\n * <kt-header sticky>\n * <a slot=\"brand\" href=\"/\">KANTO</a>\n * <nav><a href=\"/docs\">Docs</a><a href=\"/components\">Components</a></nav>\n * <kt-button slot=\"actions\" size=\"small\" icon=\"github\" label=\"GitHub\"></kt-button>\n * </kt-header>\n * ```\n */\nexport class KtHeader extends KtElement {\n static override styles = [\n KtElement.styles,\n css`\n :host {\n display: block;\n --kt-header-height: 64px;\n --kt-header-breakpoint: 900px;\n }\n\n :host([sticky]) {\n position: sticky;\n top: 0;\n z-index: var(--z-dropdown);\n }\n\n header {\n background-color: var(--surface-page);\n }\n\n /* Translucent only where the browser can actually blur; an unblurred\n semi-transparent bar is just hard to read. */\n @supports (backdrop-filter: blur(1px)) {\n :host([sticky]) header {\n background-color: color-mix(in srgb, var(--surface-page) 80%, transparent);\n backdrop-filter: blur(12px);\n }\n }\n\n :host([bordered]) header {\n border-bottom: var(--border-width) solid var(--border-subtle);\n }\n\n /* Three columns rather than a flex row, and the outer two share what is\n left equally: with flex:1 on the middle, the navigation is centred in\n the leftover space, so it sits off-centre by half the difference\n between the brand and the actions — which is exactly how far off it\n looked. Equal outer columns centre it in the bar itself. */\n .bar {\n display: grid;\n grid-template-columns: minmax(0, 1fr) auto minmax(0, 1fr);\n align-items: center;\n gap: var(--gap-card);\n min-height: var(--kt-header-height);\n padding: 0 var(--padding-card);\n }\n\n :host([nav-align='start']) .bar {\n grid-template-columns: auto minmax(0, 1fr) auto;\n }\n\n .brand {\n display: flex;\n align-items: center;\n gap: var(--gap-button);\n color: var(--text-body);\n font: var(--font-title-h6);\n line-height: 1;\n }\n\n /* A wordmark is capitals, and capitals use none of a font's descent — so\n centring the *line box* parks the letters half a descent high, which is\n about 1.5px at 18px in Manrope and reads as a misalignment rather than\n as a font. Trimming the box to the cap height and the baseline centres\n what the eye actually sees. */\n @supports (text-box: trim-both cap alphabetic) {\n .brand ::slotted(*) {\n text-box: trim-both cap alphabetic;\n }\n }\n\n .nav {\n display: flex;\n align-items: center;\n justify-content: center;\n min-width: 0;\n }\n\n :host([nav-align='start']) .nav {\n justify-content: flex-start;\n }\n\n .actions {\n display: flex;\n align-items: center;\n justify-content: flex-end;\n gap: var(--gap-button);\n }\n\n .bottom {\n padding: 0 var(--padding-card);\n }\n\n /* Hidden above the breakpoint; the container query cannot help here\n because the header spans the viewport by definition. */\n .menu-button {\n display: none;\n flex: none;\n }\n\n .panel {\n display: none;\n }\n\n @media (max-width: 899px) {\n .menu-button {\n display: inline-flex;\n }\n\n .nav {\n display: none;\n }\n\n .panel.open {\n display: block;\n padding: 0 var(--padding-card) var(--padding-form);\n border-top: var(--border-width) solid var(--border-subtle);\n }\n }\n `,\n ];\n\n @state()\n private menuOpen = false;\n\n /** Pins the header to the top of the viewport. */\n @property({ type: Boolean, reflect: true })\n sticky = false;\n\n /** Where the navigation sits: centred in the bar, or against the brand. */\n @property({ type: String, reflect: true, attribute: 'nav-align' })\n navAlign: 'center' | 'start' = 'center';\n\n @property({ type: Boolean, reflect: true })\n bordered = true;\n\n /** Accessible name for the banner, when a page has more than one. */\n @property({ type: String })\n label = '';\n\n /** Whether the collapsed navigation panel is showing. */\n get isMenuOpen(): boolean {\n return this.menuOpen;\n }\n\n /** Closes the collapsed navigation — call it after routing. */\n closeMenu(): void {\n if (!this.menuOpen) return;\n this.menuOpen = false;\n emit(this, 'kt-menu-toggle', { open: false });\n }\n\n private toggleMenu(): void {\n this.menuOpen = !this.menuOpen;\n emit(this, 'kt-menu-toggle', { open: this.menuOpen });\n }\n\n override render(): TemplateResult {\n return html`<header part=\"base\" role=\"banner\" aria-label=${this.label || nothing}>\n <div part=\"bar\" class=\"bar\">\n <div class=\"brand\"><slot name=\"brand\"></slot></div>\n\n <div class=\"nav\"><slot></slot></div>\n\n <div class=\"actions\"><slot name=\"actions\"></slot></div>\n\n <kt-button\n class=\"menu-button\"\n variant=\"secondary-no-bg\"\n size=\"small\"\n icon=${this.menuOpen ? 'x' : 'menu'}\n label=${this.menuOpen ? strings().closeMenu : strings().openMenu}\n aria-expanded=${this.menuOpen ? 'true' : 'false'}\n @click=${this.toggleMenu}\n ></kt-button>\n </div>\n\n <div class=\"panel ${this.menuOpen ? 'open' : ''}\">\n <slot name=\"menu\"></slot>\n </div>\n\n <div part=\"bottom\" class=\"bottom\"><slot name=\"bottom\"></slot></div>\n </header>`;\n }\n}\n\ndefineElement('kt-header', KtHeader);\n\ndeclare global {\n interface HTMLElementTagNameMap {\n 'kt-header': KtHeader;\n }\n}\n"],"names":["KtHeader","KtElement","css","emit","html","nothing","strings","__decorateClass","state","property","defineElement"],"mappings":";;;;;;;;;;;AAiDO,MAAMA,UAAiBC,EAAU;AAAA,EAAjC,cAAA;AAAA,UAAA,GAAA,SAAA,GA2HL,KAAQ,WAAW,IAInB,KAAA,SAAS,IAIT,KAAA,WAA+B,UAG/B,KAAA,WAAW,IAIX,KAAA,QAAQ;AAAA,EAAA;AAAA,EAzIR,OAAA;AAAA,SAAgB,SAAS;AAAA,MACvBA,EAAU;AAAA,MACVC;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,IAAA;AAAA,EAqHF;AAAA;AAAA,EAqBA,IAAI,aAAsB;AACxB,WAAO,KAAK;AAAA,EACd;AAAA;AAAA,EAGA,YAAkB;AAChB,IAAK,KAAK,aACV,KAAK,WAAW,IAChBC,EAAK,MAAM,kBAAkB,EAAE,MAAM,IAAO;AAAA,EAC9C;AAAA,EAEQ,aAAmB;AACzB,SAAK,WAAW,CAAC,KAAK,UACtBA,EAAK,MAAM,kBAAkB,EAAE,MAAM,KAAK,UAAU;AAAA,EACtD;AAAA,EAES,SAAyB;AAChC,WAAOC,iDAAoD,KAAK,SAASC,CAAO;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,iBAYnE,KAAK,WAAW,MAAM,MAAM;AAAA,kBAC3B,KAAK,WAAWC,EAAA,EAAU,YAAYA,EAAA,EAAU,QAAQ;AAAA,0BAChD,KAAK,WAAW,SAAS,OAAO;AAAA,mBACvC,KAAK,UAAU;AAAA;AAAA;AAAA;AAAA,0BAIR,KAAK,WAAW,SAAS,EAAE;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAMnD;AACF;AA7DUC,EAAA;AAAA,EADPC,EAAA;AAAM,GA1HIR,EA2HH,WAAA,UAAA;AAIRO,EAAA;AAAA,EADCE,EAAS,EAAE,MAAM,SAAS,SAAS,IAAM;AAAA,GA9H/BT,EA+HX,WAAA,QAAA;AAIAO,EAAA;AAAA,EADCE,EAAS,EAAE,MAAM,QAAQ,SAAS,IAAM,WAAW,aAAa;AAAA,GAlItDT,EAmIX,WAAA,UAAA;AAGAO,EAAA;AAAA,EADCE,EAAS,EAAE,MAAM,SAAS,SAAS,IAAM;AAAA,GArI/BT,EAsIX,WAAA,UAAA;AAIAO,EAAA;AAAA,EADCE,EAAS,EAAE,MAAM,OAAA,CAAQ;AAAA,GAzIfT,EA0IX,WAAA,OAAA;AAgDFU,EAAc,aAAaV,CAAQ;"}
@@ -1,6 +1,6 @@
1
1
  import { css as c, html as t, nothing as l } from "lit";
2
2
  import { property as s } from "lit/decorators.js";
3
- import { K as h, d as g } from "../../../chunks/kt-element-B_jjQDhg.js";
3
+ import { K as h, d as g } from "../../../chunks/kt-element-mdd5cXZX.js";
4
4
  var f = Object.defineProperty, o = (a, r, p, v) => {
5
5
  for (var e = void 0, n = a.length - 1, d; n >= 0; n--)
6
6
  (d = a[n]) && (e = d(r, p, e) || e);
@@ -1,16 +1,17 @@
1
1
  import { css as b, nothing as c, html as p } from "lit";
2
- import { queryAll as v, property as s } from "lit/decorators.js";
2
+ import { queryAll as v, property as n } from "lit/decorators.js";
3
3
  import { classMap as h } from "lit/directives/class-map.js";
4
- import { K as f, d as g } from "../../../chunks/kt-element-B_jjQDhg.js";
4
+ import { K as f, d as g } from "../../../chunks/kt-element-mdd5cXZX.js";
5
5
  import { e as m } from "../../../chunks/events-Bjl5Zmmq.js";
6
6
  import { a as x, s as y, b as k } from "../../../chunks/form-control-CxjBTt1c.js";
7
+ import { s as $ } from "../../../chunks/index-fzPIgxe2.js";
7
8
  import "../../core/kt-icon/kt-icon.js";
8
- var $ = Object.defineProperty, n = (u, t, o, i) => {
9
+ var w = Object.defineProperty, s = (u, t, i, o) => {
9
10
  for (var e = void 0, r = u.length - 1, l; r >= 0; r--)
10
- (l = u[r]) && (e = l(t, o, e) || e);
11
- return e && $(t, o, e), e;
11
+ (l = u[r]) && (e = l(t, i, e) || e);
12
+ return e && w(t, i, e), e;
12
13
  };
13
- const w = { small: 16, medium: 20, large: 24 };
14
+ const I = { small: 16, medium: 20, large: 24 };
14
15
  class a extends f {
15
16
  constructor() {
16
17
  super(...arguments), this.internals = null, this.defaultValue = null, this.options = [], this.value = null, this.size = "medium", this.orientation = "horizontal", this.disabled = !1, this.label = "", this.name = "", this.required = !1;
@@ -134,17 +135,17 @@ class a extends f {
134
135
  super.connectedCallback(), this.internals ??= x(this), this.defaultValue = this.value;
135
136
  }
136
137
  willUpdate(t) {
137
- if (t.has("value") || t.has("required")) {
138
+ if (t.has("value") || t.has("required") || this.stringsChanged(t)) {
138
139
  y(this.internals, this.value === null ? null : String(this.value));
139
- const o = this.required && this.value === null;
140
- k(this.internals, { valueMissing: o }, o ? "Select an option." : "");
140
+ const i = this.required && this.value === null;
141
+ k(this.internals, { valueMissing: i }, i ? $().selectOption : "");
141
142
  }
142
143
  }
143
144
  formResetCallback() {
144
145
  this.value = this.defaultValue;
145
146
  }
146
147
  formStateRestoreCallback(t) {
147
- this.value = this.options.find((o) => String(o.value) === t)?.value ?? t;
148
+ this.value = this.options.find((i) => String(i.value) === t)?.value ?? t;
148
149
  }
149
150
  get selectedIndex() {
150
151
  return this.options.findIndex((t) => t.value === this.value);
@@ -157,10 +158,10 @@ class a extends f {
157
158
  * and skipping disabled segments.
158
159
  */
159
160
  onKeyDown(t) {
160
- const o = this.orientation === "vertical" ? "ArrowDown" : "ArrowRight", i = this.orientation === "vertical" ? "ArrowUp" : "ArrowLeft";
161
+ const i = this.orientation === "vertical" ? "ArrowDown" : "ArrowRight", o = this.orientation === "vertical" ? "ArrowUp" : "ArrowLeft";
161
162
  let e;
162
- if (t.key === o) e = this.step(1);
163
- else if (t.key === i) e = this.step(-1);
163
+ if (t.key === i) e = this.step(1);
164
+ else if (t.key === o) e = this.step(-1);
164
165
  else if (t.key === "Home") e = this.options.findIndex((d) => !d.disabled);
165
166
  else if (t.key === "End")
166
167
  e = this.options.length - 1 - [...this.options].reverse().findIndex((d) => !d.disabled);
@@ -172,16 +173,16 @@ class a extends f {
172
173
  this.choose(r), this.updateComplete.then(() => this.segments[l]?.focus());
173
174
  }
174
175
  step(t) {
175
- const o = this.options.length;
176
- if (o === 0) return;
177
- const i = this.selectedIndex < 0 ? t === 1 ? -1 : 0 : this.selectedIndex;
178
- for (let e = 1; e <= o; e += 1) {
179
- const r = ((i + t * e) % o + o) % o;
176
+ const i = this.options.length;
177
+ if (i === 0) return;
178
+ const o = this.selectedIndex < 0 ? t === 1 ? -1 : 0 : this.selectedIndex;
179
+ for (let e = 1; e <= i; e += 1) {
180
+ const r = ((o + t * e) % i + i) % i;
180
181
  if (!this.options[r]?.disabled) return r;
181
182
  }
182
183
  }
183
184
  render() {
184
- const t = this.selectedIndex, o = t >= 0 ? t : this.options.findIndex((i) => !i.disabled);
185
+ const t = this.selectedIndex, i = t >= 0 ? t : this.options.findIndex((o) => !o.disabled);
185
186
  return p`<div
186
187
  part="base"
187
188
  class=${h({
@@ -195,8 +196,8 @@ class a extends f {
195
196
  aria-disabled=${this.disabled ? "true" : c}
196
197
  @keydown=${this.onKeyDown}
197
198
  >
198
- ${this.options.map((i, e) => {
199
- const r = i.value === this.value, l = i.label ?? "", d = !!i.icon && l === "";
199
+ ${this.options.map((o, e) => {
200
+ const r = o.value === this.value, l = o.label ?? "", d = !!o.icon && l === "";
200
201
  return p`<button
201
202
  part="option"
202
203
  type="button"
@@ -208,44 +209,44 @@ class a extends f {
208
209
  "icon-only": d
209
210
  })}
210
211
  aria-checked=${r ? "true" : "false"}
211
- aria-label=${d ? i.icon ?? "" : c}
212
- tabindex=${e === o ? 0 : -1}
213
- ?disabled=${this.disabled || i.disabled}
214
- @click=${() => this.choose(i)}
212
+ aria-label=${d ? o.icon ?? "" : c}
213
+ tabindex=${e === i ? 0 : -1}
214
+ ?disabled=${this.disabled || o.disabled}
215
+ @click=${() => this.choose(o)}
215
216
  >
216
- ${i.icon ? p`<kt-icon name=${i.icon} size=${w[this.size]}></kt-icon>` : c}
217
+ ${o.icon ? p`<kt-icon name=${o.icon} size=${I[this.size]}></kt-icon>` : c}
217
218
  ${d ? c : p`<span class="text">${l}</span>`}
218
219
  </button>`;
219
220
  })}
220
221
  </div>`;
221
222
  }
222
223
  }
223
- n([
224
+ s([
224
225
  v(".option")
225
226
  ], a.prototype, "segments");
226
- n([
227
- s({ attribute: !1 })
227
+ s([
228
+ n({ attribute: !1 })
228
229
  ], a.prototype, "options");
229
- n([
230
- s({ type: String })
230
+ s([
231
+ n({ type: String })
231
232
  ], a.prototype, "value");
232
- n([
233
- s({ type: String, reflect: !0 })
233
+ s([
234
+ n({ type: String, reflect: !0 })
234
235
  ], a.prototype, "size");
235
- n([
236
- s({ type: String, reflect: !0 })
236
+ s([
237
+ n({ type: String, reflect: !0 })
237
238
  ], a.prototype, "orientation");
238
- n([
239
- s({ type: Boolean, reflect: !0 })
239
+ s([
240
+ n({ type: Boolean, reflect: !0 })
240
241
  ], a.prototype, "disabled");
241
- n([
242
- s({ type: String })
242
+ s([
243
+ n({ type: String })
243
244
  ], a.prototype, "label");
244
- n([
245
- s({ type: String })
245
+ s([
246
+ n({ type: String })
246
247
  ], a.prototype, "name");
247
- n([
248
- s({ type: Boolean, reflect: !0 })
248
+ s([
249
+ n({ type: Boolean, reflect: !0 })
249
250
  ], a.prototype, "required");
250
251
  g("kt-segmented-control", a);
251
252
  export {