@area8975/ui 0.2.2-dev.48 → 0.2.2-dev.50

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 (182) hide show
  1. package/README.md +3 -2
  2. package/fesm2022/area8975-ui-alert.mjs +113 -0
  3. package/fesm2022/area8975-ui-alert.mjs.map +1 -0
  4. package/fesm2022/area8975-ui-avatar.mjs +157 -0
  5. package/fesm2022/area8975-ui-avatar.mjs.map +1 -0
  6. package/fesm2022/area8975-ui-badge.mjs +116 -0
  7. package/fesm2022/area8975-ui-badge.mjs.map +1 -0
  8. package/fesm2022/area8975-ui-button.mjs +314 -0
  9. package/fesm2022/area8975-ui-button.mjs.map +1 -0
  10. package/fesm2022/area8975-ui-calendar.mjs +549 -0
  11. package/fesm2022/area8975-ui-calendar.mjs.map +1 -0
  12. package/fesm2022/area8975-ui-card-header.mjs +96 -0
  13. package/fesm2022/area8975-ui-card-header.mjs.map +1 -0
  14. package/fesm2022/area8975-ui-card.mjs +73 -0
  15. package/fesm2022/area8975-ui-card.mjs.map +1 -0
  16. package/fesm2022/area8975-ui-chart-palette.mjs +225 -0
  17. package/fesm2022/area8975-ui-chart-palette.mjs.map +1 -0
  18. package/fesm2022/area8975-ui-charts.mjs +2813 -0
  19. package/fesm2022/area8975-ui-charts.mjs.map +1 -0
  20. package/fesm2022/area8975-ui-checkbox.mjs +202 -0
  21. package/fesm2022/area8975-ui-checkbox.mjs.map +1 -0
  22. package/fesm2022/area8975-ui-colour.mjs +200 -0
  23. package/fesm2022/area8975-ui-colour.mjs.map +1 -0
  24. package/fesm2022/area8975-ui-container.mjs +40 -0
  25. package/fesm2022/area8975-ui-container.mjs.map +1 -0
  26. package/fesm2022/area8975-ui-counter.mjs +246 -0
  27. package/fesm2022/area8975-ui-counter.mjs.map +1 -0
  28. package/fesm2022/area8975-ui-date-range-picker.mjs +554 -0
  29. package/fesm2022/area8975-ui-date-range-picker.mjs.map +1 -0
  30. package/fesm2022/area8975-ui-datepicker.mjs +547 -0
  31. package/fesm2022/area8975-ui-datepicker.mjs.map +1 -0
  32. package/fesm2022/area8975-ui-disclosure.mjs +279 -0
  33. package/fesm2022/area8975-ui-disclosure.mjs.map +1 -0
  34. package/fesm2022/area8975-ui-drawer.mjs +106 -0
  35. package/fesm2022/area8975-ui-drawer.mjs.map +1 -0
  36. package/fesm2022/area8975-ui-dropdown-button.mjs +141 -0
  37. package/fesm2022/area8975-ui-dropdown-button.mjs.map +1 -0
  38. package/fesm2022/area8975-ui-dropdown-menu.mjs +96 -0
  39. package/fesm2022/area8975-ui-dropdown-menu.mjs.map +1 -0
  40. package/fesm2022/area8975-ui-dropdown.mjs +208 -0
  41. package/fesm2022/area8975-ui-dropdown.mjs.map +1 -0
  42. package/fesm2022/area8975-ui-dropzone.mjs +332 -0
  43. package/fesm2022/area8975-ui-dropzone.mjs.map +1 -0
  44. package/fesm2022/area8975-ui-field.mjs +191 -0
  45. package/fesm2022/area8975-ui-field.mjs.map +1 -0
  46. package/fesm2022/area8975-ui-file-input.mjs +340 -0
  47. package/fesm2022/area8975-ui-file-input.mjs.map +1 -0
  48. package/fesm2022/area8975-ui-file.mjs +47 -0
  49. package/fesm2022/area8975-ui-file.mjs.map +1 -0
  50. package/fesm2022/area8975-ui-format.mjs +70 -0
  51. package/fesm2022/area8975-ui-format.mjs.map +1 -0
  52. package/fesm2022/area8975-ui-input-addon.mjs +42 -0
  53. package/fesm2022/area8975-ui-input-addon.mjs.map +1 -0
  54. package/fesm2022/area8975-ui-input-group.mjs +86 -0
  55. package/fesm2022/area8975-ui-input-group.mjs.map +1 -0
  56. package/fesm2022/area8975-ui-input.mjs +682 -0
  57. package/fesm2022/area8975-ui-input.mjs.map +1 -0
  58. package/fesm2022/area8975-ui-kpi.mjs +167 -0
  59. package/fesm2022/area8975-ui-kpi.mjs.map +1 -0
  60. package/fesm2022/area8975-ui-layout.mjs +63 -0
  61. package/fesm2022/area8975-ui-layout.mjs.map +1 -0
  62. package/fesm2022/area8975-ui-loading.mjs +76 -0
  63. package/fesm2022/area8975-ui-loading.mjs.map +1 -0
  64. package/fesm2022/area8975-ui-modal-close-btn.mjs +89 -0
  65. package/fesm2022/area8975-ui-modal-close-btn.mjs.map +1 -0
  66. package/fesm2022/area8975-ui-modal.mjs +235 -0
  67. package/fesm2022/area8975-ui-modal.mjs.map +1 -0
  68. package/fesm2022/area8975-ui-money.mjs +230 -0
  69. package/fesm2022/area8975-ui-money.mjs.map +1 -0
  70. package/fesm2022/area8975-ui-overlay.mjs +317 -0
  71. package/fesm2022/area8975-ui-overlay.mjs.map +1 -0
  72. package/fesm2022/area8975-ui-pagination.mjs +152 -0
  73. package/fesm2022/area8975-ui-pagination.mjs.map +1 -0
  74. package/fesm2022/area8975-ui-private.mjs +63 -0
  75. package/fesm2022/area8975-ui-private.mjs.map +1 -0
  76. package/fesm2022/area8975-ui-progress.mjs +307 -0
  77. package/fesm2022/area8975-ui-progress.mjs.map +1 -0
  78. package/fesm2022/area8975-ui-radio.mjs +199 -0
  79. package/fesm2022/area8975-ui-radio.mjs.map +1 -0
  80. package/fesm2022/area8975-ui-rich-text-editor.mjs +778 -0
  81. package/fesm2022/area8975-ui-rich-text-editor.mjs.map +1 -0
  82. package/fesm2022/area8975-ui-search.mjs +266 -0
  83. package/fesm2022/area8975-ui-search.mjs.map +1 -0
  84. package/fesm2022/area8975-ui-segmented.mjs +118 -0
  85. package/fesm2022/area8975-ui-segmented.mjs.map +1 -0
  86. package/fesm2022/area8975-ui-select.mjs +926 -0
  87. package/fesm2022/area8975-ui-select.mjs.map +1 -0
  88. package/fesm2022/area8975-ui-sidebar-group.mjs +60 -0
  89. package/fesm2022/area8975-ui-sidebar-group.mjs.map +1 -0
  90. package/fesm2022/area8975-ui-sidebar-item.mjs +107 -0
  91. package/fesm2022/area8975-ui-sidebar-item.mjs.map +1 -0
  92. package/fesm2022/area8975-ui-sidebar.mjs +109 -0
  93. package/fesm2022/area8975-ui-sidebar.mjs.map +1 -0
  94. package/fesm2022/area8975-ui-skeleton.mjs +116 -0
  95. package/fesm2022/area8975-ui-skeleton.mjs.map +1 -0
  96. package/fesm2022/area8975-ui-stat.mjs +55 -0
  97. package/fesm2022/area8975-ui-stat.mjs.map +1 -0
  98. package/fesm2022/area8975-ui-switch.mjs +132 -0
  99. package/fesm2022/area8975-ui-switch.mjs.map +1 -0
  100. package/fesm2022/area8975-ui-tab.mjs +217 -0
  101. package/fesm2022/area8975-ui-tab.mjs.map +1 -0
  102. package/fesm2022/area8975-ui-table-filters.mjs +499 -0
  103. package/fesm2022/area8975-ui-table-filters.mjs.map +1 -0
  104. package/fesm2022/area8975-ui-table.mjs +1237 -0
  105. package/fesm2022/area8975-ui-table.mjs.map +1 -0
  106. package/fesm2022/area8975-ui-textarea.mjs +375 -0
  107. package/fesm2022/area8975-ui-textarea.mjs.map +1 -0
  108. package/fesm2022/area8975-ui-theme.mjs +246 -0
  109. package/fesm2022/area8975-ui-theme.mjs.map +1 -0
  110. package/fesm2022/area8975-ui-time-select.mjs +170 -0
  111. package/fesm2022/area8975-ui-time-select.mjs.map +1 -0
  112. package/fesm2022/area8975-ui-toast.mjs +269 -0
  113. package/fesm2022/area8975-ui-toast.mjs.map +1 -0
  114. package/fesm2022/area8975-ui-toaster.mjs +117 -0
  115. package/fesm2022/area8975-ui-toaster.mjs.map +1 -0
  116. package/fesm2022/area8975-ui-tooltip.mjs +196 -0
  117. package/fesm2022/area8975-ui-tooltip.mjs.map +1 -0
  118. package/fesm2022/area8975-ui-user-menu.mjs +186 -0
  119. package/fesm2022/area8975-ui-user-menu.mjs.map +1 -0
  120. package/fesm2022/area8975-ui.mjs +0 -16269
  121. package/package.json +237 -1
  122. package/types/area8975-ui-alert.d.ts +25 -0
  123. package/types/area8975-ui-avatar.d.ts +40 -0
  124. package/types/area8975-ui-badge.d.ts +31 -0
  125. package/types/area8975-ui-button.d.ts +129 -0
  126. package/types/area8975-ui-calendar.d.ts +177 -0
  127. package/types/area8975-ui-card-header.d.ts +28 -0
  128. package/types/area8975-ui-card.d.ts +18 -0
  129. package/types/area8975-ui-chart-palette.d.ts +176 -0
  130. package/types/area8975-ui-charts.d.ts +747 -0
  131. package/types/area8975-ui-checkbox.d.ts +61 -0
  132. package/types/area8975-ui-colour.d.ts +31 -0
  133. package/types/area8975-ui-container.d.ts +5 -0
  134. package/types/area8975-ui-counter.d.ts +43 -0
  135. package/types/area8975-ui-date-range-picker.d.ts +132 -0
  136. package/types/area8975-ui-datepicker.d.ts +124 -0
  137. package/types/area8975-ui-disclosure.d.ts +79 -0
  138. package/types/area8975-ui-drawer.d.ts +25 -0
  139. package/types/area8975-ui-dropdown-button.d.ts +32 -0
  140. package/types/area8975-ui-dropdown-menu.d.ts +25 -0
  141. package/types/area8975-ui-dropdown.d.ts +56 -0
  142. package/types/area8975-ui-dropzone.d.ts +96 -0
  143. package/types/area8975-ui-field.d.ts +72 -0
  144. package/types/area8975-ui-file-input.d.ts +72 -0
  145. package/types/area8975-ui-file.d.ts +21 -0
  146. package/types/area8975-ui-format.d.ts +37 -0
  147. package/types/area8975-ui-input-addon.d.ts +10 -0
  148. package/types/area8975-ui-input-group.d.ts +18 -0
  149. package/types/area8975-ui-input.d.ts +224 -0
  150. package/types/area8975-ui-kpi.d.ts +36 -0
  151. package/types/area8975-ui-layout.d.ts +7 -0
  152. package/types/area8975-ui-loading.d.ts +16 -0
  153. package/types/area8975-ui-modal-close-btn.d.ts +14 -0
  154. package/types/area8975-ui-modal.d.ts +45 -0
  155. package/types/area8975-ui-money.d.ts +77 -0
  156. package/types/area8975-ui-overlay.d.ts +75 -0
  157. package/types/area8975-ui-pagination.d.ts +27 -0
  158. package/types/area8975-ui-private.d.ts +20 -0
  159. package/types/area8975-ui-progress.d.ts +127 -0
  160. package/types/area8975-ui-radio.d.ts +61 -0
  161. package/types/area8975-ui-rich-text-editor.d.ts +165 -0
  162. package/types/area8975-ui-search.d.ts +56 -0
  163. package/types/area8975-ui-segmented.d.ts +41 -0
  164. package/types/area8975-ui-select.d.ts +293 -0
  165. package/types/area8975-ui-sidebar-group.d.ts +15 -0
  166. package/types/area8975-ui-sidebar-item.d.ts +20 -0
  167. package/types/area8975-ui-sidebar.d.ts +16 -0
  168. package/types/area8975-ui-skeleton.d.ts +35 -0
  169. package/types/area8975-ui-stat.d.ts +13 -0
  170. package/types/area8975-ui-switch.d.ts +32 -0
  171. package/types/area8975-ui-tab.d.ts +45 -0
  172. package/types/area8975-ui-table-filters.d.ts +138 -0
  173. package/types/area8975-ui-table.d.ts +371 -0
  174. package/types/area8975-ui-textarea.d.ts +126 -0
  175. package/types/area8975-ui-theme.d.ts +61 -0
  176. package/types/area8975-ui-time-select.d.ts +35 -0
  177. package/types/area8975-ui-toast.d.ts +78 -0
  178. package/types/area8975-ui-toaster.d.ts +23 -0
  179. package/types/area8975-ui-tooltip.d.ts +47 -0
  180. package/types/area8975-ui-user-menu.d.ts +39 -0
  181. package/types/area8975-ui.d.ts +1 -4464
  182. package/fesm2022/area8975-ui.mjs.map +0 -1
@@ -0,0 +1 @@
1
+ {"version":3,"file":"area8975-ui-select.mjs","names":[],"sources":["../../../projects/ui/select/select.component.ts","../../../projects/ui/select/select.component.html","../../../projects/ui/select/select.datasource.ts","../../../projects/ui/select/select.types.ts"],"sourcesContent":["import { NgTemplateOutlet } from '@angular/common';\nimport {\n afterNextRender,\n booleanAttribute,\n ChangeDetectorRef,\n Component,\n computed,\n contentChild,\n DestroyRef,\n effect,\n ElementRef,\n inject,\n Injector,\n input,\n model,\n output,\n signal,\n TemplateRef,\n untracked\n} from '@angular/core';\nimport { takeUntilDestroyed, toObservable } from '@angular/core/rxjs-interop';\n\nimport { UiBadgeComponent } from '@area8975/ui/badge';\nimport { UiCardComponent } from '@area8975/ui/card';\nimport { UiDropdownComponent } from '@area8975/ui/dropdown';\nimport { UiDropdownDirective } from '@area8975/ui/dropdown';\nimport { UiInputComponent } from '@area8975/ui/input';\nimport { InputValidation } from '@area8975/ui/input';\nimport { UiOverlayCloseBehaviour } from '@area8975/ui/overlay';\nimport { Placement } from '@floating-ui/dom';\nimport { NgIcon, provideIcons } from '@ng-icons/core';\nimport {\n heroCheck,\n heroChevronDown,\n heroPlus,\n heroXMark\n} from '@ng-icons/heroicons/outline';\nimport {\n catchError,\n debounceTime,\n Observable,\n of,\n skip,\n Subject,\n switchMap\n} from 'rxjs';\n\nimport { SelectDataSource, SelectDataSourceContent } from './select.datasource';\nimport {\n SearchMode,\n SelectLeadingContext,\n SelectMultipleDisplay,\n SelectOptionContext,\n SelectRow,\n SelectTriggerContext\n} from './select.types';\n\n\nlet nextId = 0;\n\n@Component({\n selector: 'ui-select',\n templateUrl: './select.component.html',\n styleUrl: './select.component.css',\n imports: [\n UiDropdownComponent,\n UiDropdownDirective,\n UiInputComponent,\n UiBadgeComponent,\n UiCardComponent,\n NgIcon,\n NgTemplateOutlet\n ],\n host: { '[attr.id]': 'null', '(focusout)': 'onFocusOut($event)' },\n providers: [provideIcons({\n heroChevronDown,\n heroXMark,\n heroCheck,\n heroPlus\n })]\n})\nexport class UiSelectComponent<Model = unknown> {\n readonly isOpen = signal(false);\n readonly placement = input<Placement>('bottom-start');\n readonly closeBehaviour = input<UiOverlayCloseBehaviour>(\n 'whenClickOutside'\n );\n\n readonly dataSource = input.required<SelectDataSource<Model>>();\n readonly items = signal<Model[]>([]);\n\n readonly placeholder = input<string>('Select an option');\n\n /** Goes on the trigger (or the inline search box), pass it to ui-field's `for`. */\n readonly id = input<string>('');\n readonly describedBy = input<string>('');\n\n readonly pageSize = input<number>(10);\n readonly searchMode = input<SearchMode>('none');\n\n // added: disabled state, previously had CSS but nothing set it\n readonly disabled = input(false, { transform: booleanAttribute });\n // added: validation styling to match ui-input\n readonly validationState = model<InputValidation>(null);\n\n // opt-in, most selects back a required value where clearing isn't valid\n readonly clearable = input(false, { transform: booleanAttribute });\n readonly clearLabel = input<string>('None');\n\n /**\n * Offers a \"Create\" row when a search matches nothing. Needs a\n * searchMode, the parent handles `create` and adds the new item.\n */\n readonly creatable = input(false, { transform: booleanAttribute });\n readonly createLabel = input<(query: string) => string>(query =>\n `Create \"${query}\"`\n );\n\n /** Puts a heading above each run of items in the same group. Expects items sorted by group. */\n readonly groupBy = input<((item: Model) => string | null) | null>(null);\n\n /** Scrolls the selected option into view when the list opens. */\n readonly scrollToSelected = input(true, { transform: booleanAttribute });\n\n /** Lets several items be picked, bound through `selectedItems`. */\n readonly multiple = input(false, { transform: booleanAttribute });\n readonly multipleDisplay = input<SelectMultipleDisplay>('text');\n\n /** In text display, swaps the list of names for a count past this many. 0 always counts. */\n readonly counterAfter = input<number | null>(null);\n readonly counterLabel = input<(count: number) => string>(count =>\n `${count} selected`\n );\n\n readonly compareWith = input<(a: Model, b: Model) => boolean>(\n (a, b) => a === b\n );\n\n readonly displayWith = input<(item: Model) => string>(\n item => `${item}`\n );\n\n readonly selectionChange = output<Model | null>();\n\n /** Emits the search text when the \"Create\" row is picked. */\n readonly create = output<string>();\n // changed to a model so a selection can be bound in from outside\n readonly selectedItem = model<Model | null>(null);\n readonly selectedItems = model<Model[]>([]);\n readonly query = signal('');\n readonly loading = signal(false);\n readonly hasMore = signal(true);\n\n readonly optionTemplate = contentChild<\n TemplateRef<SelectOptionContext<Model>>\n >('option');\n readonly triggerTemplate = contentChild<\n TemplateRef<SelectTriggerContext<Model>>\n >('trigger');\n\n /** With an inline search, shown before the chosen item's text, e.g. its colour. Single select only. */\n readonly leadingTemplate = contentChild<\n TemplateRef<SelectLeadingContext<Model>>\n >('leading');\n\n /** Index into the pickable rows, the one keyboard focus sits on. */\n readonly activeIndex = signal(0);\n\n readonly listId = `ui-select-${nextId++}`;\n\n readonly hasSelection = computed(() =>\n this.multiple()\n ? this.selectedItems().length > 0\n : this.selectedItem() !== null\n );\n\n readonly triggerLabel = computed(() => {\n const display = this.displayWith();\n\n if (!this.multiple()) {\n const selected = this.selectedItem();\n\n return selected !== null ? display(selected) : this.placeholder();\n }\n\n const selected = this.selectedItems();\n const counterAfter = this.counterAfter();\n\n if (!selected.length) {\n return this.placeholder();\n }\n\n return counterAfter !== null && selected.length > counterAfter\n ? this.counterLabel()(selected.length)\n : selected.map(display).join(', ');\n });\n\n readonly isEmpty = computed(() =>\n this.multiple() ? !this.selectedItems().length : this.selectedItem() === null\n );\n\n /** Tags only replace the trigger text when there's no inline search box. */\n readonly showTags = computed(() =>\n this.multiple() &&\n this.multipleDisplay() === 'tags' &&\n this.searchMode() !== 'inline'\n );\n\n readonly showLeading = computed(() =>\n !!this.leadingTemplate() &&\n !this.multiple() &&\n this.selectedItem() !== null\n );\n\n /** Typing replaces the chosen item's text, so its leading content sits out the search. */\n readonly leadingHidden = computed(() =>\n this.isOpen() && this.query() !== ''\n );\n\n /** The text to create from, or null when there's nothing to offer. */\n readonly createQuery = computed(() => {\n const query = this.query().trim();\n const display = this.displayWith();\n\n if (!this.creatable() || !query || this.loading()) {\n return null;\n }\n\n const exists = this.items().some(item =>\n display(item).toLowerCase() === query.toLowerCase()\n );\n\n return exists ? null : query;\n });\n\n readonly rows = computed<SelectRow<Model>[]>(() => {\n const rows: SelectRow<Model>[] = [];\n const groupBy = this.groupBy();\n const display = this.displayWith();\n const createQuery = this.createQuery();\n\n let index = 0;\n let group: string | null | undefined;\n\n if (this.clearable() && this.hasSelection()) {\n rows.push({ kind: 'clear', id: this.rowId(index), index: index++ });\n }\n\n for (const item of this.items()) {\n if (groupBy) {\n const next = groupBy(item);\n\n if (next !== group && next) {\n rows.push({\n kind: 'group',\n id: `${this.listId}-group-${rows.length}`,\n label: next\n });\n }\n\n group = next;\n }\n\n rows.push({\n kind: 'item',\n id: this.rowId(index),\n index: index++,\n item,\n label: display(item),\n selected: this.isSelected(item)\n });\n }\n\n if (createQuery) {\n rows.push({\n kind: 'create',\n id: this.rowId(index),\n index,\n query: createQuery\n });\n }\n\n return rows;\n });\n\n private readonly pickable = computed(() =>\n this.rows().filter(row => row.kind !== 'group')\n );\n\n readonly activeId = computed(() =>\n this.isOpen() ? this.pickable()[this.activeIndex()]?.id ?? null : null\n );\n\n private page = 0;\n\n // one shared stream for every fetch, so a new request cancels whatever was still in flight\n private readonly load$ = new Subject<void>();\n\n private readonly host = inject<ElementRef<HTMLElement>>(ElementRef);\n private readonly injector = inject(Injector);\n private readonly destroyRef = inject(DestroyRef);\n private readonly cdr = inject(ChangeDetectorRef);\n\n constructor() {\n // reloads when a new data source comes in, e.g. after creating an item\n effect(() => {\n this.dataSource();\n untracked(() => this.loadFirstPage());\n });\n\n // start on the selected option, and bring it into view\n effect(() => {\n if (!this.isOpen()) {\n return;\n }\n\n untracked(() => {\n const selected = this.pickable().findIndex(row =>\n row.kind === 'item' && row.selected\n );\n\n this.activeIndex.set(\n this.scrollToSelected() && selected >= 0 ? selected : 0\n );\n\n afterNextRender(() => {\n if (this.scrollToSelected()) {\n this.scrollActiveIntoView();\n }\n\n if (this.searchMode() === 'dropdown') {\n this.searchInput()?.focus();\n }\n }, { injector: this.injector });\n });\n });\n\n // debounce the query signal itself instead of a separate subject\n toObservable(this.query).pipe(\n debounceTime(300),\n skip(1), // skip the initial value, the data source effect already loads that\n takeUntilDestroyed(this.destroyRef)\n ).subscribe(() => this.loadFirstPage());\n\n // switchMap cancels the previous request, fixing stale responses overwriting newer ones\n this.load$.pipe(\n switchMap(() => this.fetchPage()),\n takeUntilDestroyed(this.destroyRef)\n ).subscribe(result => this.applyResult(result));\n }\n\n private fetchPage(): Observable<SelectDataSourceContent<Model> | null> {\n this.loading.set(true);\n\n const request = this.dataSource().load({\n query: this.query(),\n page: this.page,\n size: this.pageSize()\n });\n\n return request.pipe(catchError(() => of(null)));\n }\n\n private applyResult(result: SelectDataSourceContent<Model> | null): void {\n this.loading.set(false);\n\n if (result) {\n this.items.update(items => [...items, ...result.items]);\n this.hasMore.set(result.hasMore);\n }\n\n this.cdr.markForCheck();\n }\n\n open(): void {\n if (!this.disabled()) {\n this.isOpen.set(true);\n }\n }\n\n toggle(): void {\n if (this.isOpen()) {\n this.isOpen.set(false);\n } else {\n this.open();\n }\n }\n\n select(item: Model): void {\n this.selectedItem.set(item);\n this.selectionChange.emit(item);\n }\n\n isSelected(item: Model): boolean {\n const compare = this.compareWith();\n\n if (item === null) {\n return false;\n }\n\n if (this.multiple()) {\n return this.selectedItems().some(selected =>\n compare(selected, item)\n );\n }\n\n const selected = this.selectedItem();\n\n return selected !== null && compare(selected, item);\n }\n\n toggleItem(item: Model): void {\n const compare = this.compareWith();\n\n this.selectedItems.update(selected =>\n this.isSelected(item)\n ? selected.filter(existing => !compare(existing, item))\n : [...selected, item]\n );\n }\n\n removeItem(item: Model): void {\n const compare = this.compareWith();\n\n this.selectedItems.update(selected =>\n selected.filter(existing => !compare(existing, item))\n );\n }\n\n clear(): void {\n if (this.multiple()) {\n this.selectedItems.set([]);\n } else {\n this.selectedItem.set(null);\n this.selectionChange.emit(null);\n }\n\n this.isOpen.set(false);\n this.focusTrigger();\n\n if (this.searchMode() === 'inline') {\n this.query.set('');\n }\n }\n\n onItemClick(item: Model): void {\n // multiple stays open so several can be ticked in one go\n if (this.multiple()) {\n this.toggleItem(item);\n return;\n }\n\n this.select(item);\n this.isOpen.set(false);\n this.focusTrigger();\n\n // The behaviour of clearing the inline search flows better than\n // leaving it as is. Clicking into the input with a value already\n // selected will reveal the previous query which may be confusing.\n if (this.searchMode() === 'inline') {\n this.query.set('');\n }\n }\n\n onCreate(): void {\n const query = this.createQuery();\n\n if (!query) {\n return;\n }\n\n this.create.emit(query);\n this.query.set('');\n\n if (!this.multiple()) {\n this.isOpen.set(false);\n this.focusTrigger();\n }\n }\n\n onKeydown(event: KeyboardEvent): void {\n const count = this.pickable().length;\n // space types in search boxes, only the plain trigger treats it as a pick\n const isSpacePick = event.key === ' ' && this.searchMode() === 'none';\n\n switch (event.key) {\n case 'ArrowDown':\n case 'ArrowUp':\n event.preventDefault();\n\n if (!this.isOpen()) {\n this.open();\n return;\n }\n\n this.moveActive(event.key === 'ArrowDown' ? 1 : -1, count);\n return;\n case 'Home':\n case 'End':\n if (this.isOpen() && count && this.searchMode() === 'none') {\n event.preventDefault();\n this.setActive(event.key === 'Home' ? 0 : count - 1);\n }\n return;\n case 'Enter':\n case ' ':\n if (event.key === ' ' && !isSpacePick) {\n return;\n }\n\n event.preventDefault();\n\n if (!this.isOpen()) {\n this.open();\n } else {\n this.pickActive();\n }\n return;\n case 'Escape':\n // the overlay closes itself, focus just needs a home\n this.focusTrigger();\n return;\n }\n }\n\n onFocusOut(event: FocusEvent): void {\n const next = event.relatedTarget;\n\n if (this.closeBehaviour() === 'none') {\n return;\n }\n\n // tabbing away closes it, moving between the trigger and the list doesn't\n if (\n !(next instanceof Node) ||\n !this.host.nativeElement.contains(next)\n ) {\n this.isOpen.set(false);\n }\n }\n\n setActive(index: number): void {\n this.activeIndex.set(index);\n\n afterNextRender(() => this.scrollActiveIntoView(), {\n injector: this.injector\n });\n }\n\n loadFirstPage(): void {\n this.page = 0;\n this.items.set([]);\n this.hasMore.set(true);\n\n this.load$.next();\n }\n\n loadNextPage(): void {\n if (this.loading() || !this.hasMore()) {\n return;\n }\n\n this.page++;\n this.load$.next();\n }\n\n onQueryChange(query: string): void {\n // sets straight away so the search box doesn't fight the user's typing, the\n // constructor's toObservable pipeline debounces the actual reload\n this.query.set(query);\n this.activeIndex.set(0);\n this.open();\n }\n\n onScroll(scrollContainer: HTMLElement): void {\n const remainingPixels = scrollContainer.scrollHeight\n - scrollContainer.scrollTop\n - scrollContainer.clientHeight;\n\n if (remainingPixels < 48) {\n this.loadNextPage();\n }\n }\n\n private pickActive(): void {\n const row = this.pickable()[this.activeIndex()];\n\n if (!row) {\n return;\n }\n\n if (row.kind === 'clear') {\n this.clear();\n } else if (row.kind === 'create') {\n this.onCreate();\n } else if (row.kind === 'item') {\n this.onItemClick(row.item);\n }\n }\n\n private moveActive(step: number, count: number): void {\n if (count) {\n this.setActive((this.activeIndex() + step + count) % count);\n }\n }\n\n private scrollActiveIntoView(): void {\n const id = this.activeId();\n\n if (id) {\n this.host.nativeElement\n .querySelector(`#${id}`)\n ?.scrollIntoView({ block: 'nearest' });\n }\n }\n\n private focusTrigger(): void {\n const trigger = this.searchMode() === 'inline'\n ? this.searchInput()\n : this.host.nativeElement.querySelector<HTMLElement>('.ui-select');\n\n trigger?.focus();\n }\n\n // the inline box or the one inside the dropdown, never both\n private searchInput(): HTMLInputElement | null {\n return this.host.nativeElement.querySelector('ui-input input');\n }\n\n private rowId(index: number): string {\n return `${this.listId}-${index}`;\n }\n}\n","<ui-dropdown\n [isOpen]=\"isOpen\"\n [placement]=\"placement()\"\n [closeBehaviour]=\"closeBehaviour()\"\n matchWidth=\"minWidth\"\n class=\"w-full\"\n>\n @if (searchMode() === 'inline') {\n <ui-input\n [value]=\"isOpen() ? query() : triggerLabel()\"\n (valueChange)=\"onQueryChange($event)\"\n [placeholder]=\"triggerLabel()\"\n [disabled]=\"disabled()\"\n [id]=\"id()\"\n [describedBy]=\"describedBy()\"\n [ariaExpanded]=\"isOpen()\"\n [ariaControls]=\"listId\"\n [ariaActiveDescendant]=\"activeId()\"\n inputRole=\"combobox\"\n ariaAutocomplete=\"list\"\n ariaHasPopup=\"listbox\"\n class=\"border-0!\"\n [classes]=\"showLeading() ? 'h-auto! py-1.5! ps-2!' : 'h-auto! py-1.5!'\"\n autocomplete=\"off\"\n (click)=\"toggle()\"\n (keydown)=\"onKeydown($event)\"\n >\n @if (showLeading()) {\n <ng-template #leading>\n <!-- hidden rather than removed, so the text doesn't move -->\n <span class=\"ui-select-leading\" [class.invisible]=\"leadingHidden()\">\n <ng-container\n *ngTemplateOutlet=\"leadingTemplate()!; context: { $implicit: selectedItem()! }\"\n />\n </span>\n </ng-template>\n }\n\n <ng-template #trailing>\n <ng-icon\n name=\"heroChevronDown\"\n class=\"mx-3 size-4 text-muted-foreground transition-transform duration-100 shrink-0\"\n [class.rotate-180]=\"isOpen()\"\n />\n </ng-template>\n </ui-input>\n } @else {\n <div\n class=\"ui-select-trigger\"\n [class.ui-select-trigger--tags]=\"showTags()\"\n >\n <button\n type=\"button\"\n class=\"flex justify-between items-center gap-2 px-3 py-1.5 text-left ui-select\"\n aria-haspopup=\"listbox\"\n [attr.id]=\"id() || null\"\n [attr.aria-describedby]=\"describedBy() || null\"\n [attr.aria-expanded]=\"isOpen()\"\n [attr.aria-controls]=\"listId\"\n [attr.aria-activedescendant]=\"searchMode() === 'none' ? activeId() : null\"\n [disabled]=\"disabled()\"\n [attr.data-invalid]=\"validationState() === false ? '' : null\"\n [attr.data-valid]=\"validationState() === true ? '' : null\"\n (click)=\"toggle()\"\n (keydown)=\"onKeydown($event)\"\n >\n @if (showTags()) {\n <!-- the visible tags sit on top, this names the button for screen readers -->\n <span class=\"sr-only\">{{ triggerLabel() }}</span>\n } @else if (!multiple() && triggerTemplate() && selectedItem() !== null) {\n <span class=\"flex items-center gap-2 min-w-0 ui-text-body\">\n <ng-container\n *ngTemplateOutlet=\"triggerTemplate()!; context: { $implicit: selectedItem()! }\"\n />\n </span>\n } @else if (multiple()) {\n <span class=\"ui-text-body ui-select-label\" [class.text-muted-foreground-1]=\"isEmpty()\">\n <span\n class=\"ui-select-label-sizer\"\n aria-hidden=\"true\"\n >{{ placeholder() }}</span>\n <span class=\"ui-select-label-text\">{{\n triggerLabel()\n }}</span>\n </span>\n } @else {\n <span class=\"ui-text-body truncate\" [class.text-muted-foreground-1]=\"isEmpty()\">{{\n triggerLabel()\n }}</span>\n }\n\n <ng-icon\n name=\"heroChevronDown\"\n class=\"ms-auto size-4 text-muted-foreground transition-transform duration-100 shrink-0\"\n [class.rotate-180]=\"isOpen()\"\n />\n </button>\n\n @if (showTags()) {\n <span\n class=\"ui-text-body ui-select-tags-sizer\"\n aria-hidden=\"true\"\n >\n {{ placeholder() }}\n </span>\n\n <div class=\"ui-select-tags\">\n @for (item of selectedItems(); track $index) {\n <ui-badge\n intent=\"secondary\"\n appearance=\"soft\"\n size=\"xs\"\n class=\"ui-select-tag ui-text-caption\"\n >\n <span class=\"truncate\">{{\n displayWith()(item)\n }}</span>\n\n @if (!disabled()) {\n <button\n type=\"button\"\n class=\"ui-select-tag-remove\"\n [attr.aria-label]=\"'Remove ' + displayWith()(item)\"\n (click)=\"removeItem(item)\"\n >\n <ng-icon\n name=\"heroXMark\"\n class=\"size-3 shrink-0\"\n />\n </button>\n }\n </ui-badge>\n } @empty {\n <span\n class=\"text-muted-foreground-1 ui-text-body truncate\"\n >\n {{ placeholder() }}\n </span>\n }\n </div>\n }\n </div>\n }\n\n @if (isOpen()) {\n <div uiDropdownContent class=\"py-2\">\n <ui-card radius=\"lg\" class=\"divide-y overflow-hidden\">\n @if (searchMode() === 'dropdown') {\n <div class=\"p-2\">\n <ui-input\n [value]=\"query()\"\n (valueChange)=\"onQueryChange($event)\"\n (keydown)=\"onKeydown($event)\"\n [ariaExpanded]=\"true\"\n [ariaControls]=\"listId\"\n [ariaActiveDescendant]=\"activeId()\"\n inputRole=\"combobox\"\n ariaAutocomplete=\"list\"\n ariaLabel=\"Search options\"\n autocomplete=\"off\"\n placeholder=\"Search...\"\n />\n </div>\n }\n\n <div\n #scrollContainer\n class=\"py-1 max-h-60 overflow-y-auto\"\n role=\"listbox\"\n [attr.id]=\"listId\"\n [attr.aria-multiselectable]=\"multiple() || null\"\n (scroll)=\"onScroll(scrollContainer)\"\n >\n @for (row of rows(); track row.id) {\n @switch (row.kind) {\n @case ('group') {\n <div\n class=\"ui-text-caption ui-select-group\"\n role=\"presentation\"\n >\n {{ row.label }}\n </div>\n }\n @case ('clear') {\n <button\n type=\"button\"\n role=\"option\"\n aria-selected=\"false\"\n tabindex=\"-1\"\n class=\"text-muted-foreground-1 ui-text-body-alt ui-select-option\"\n [attr.id]=\"row.id\"\n [attr.data-active]=\"row.index === activeIndex() ? '' : null\"\n (mousedown)=\"$event.preventDefault()\"\n (mouseenter)=\"activeIndex.set(row.index)\"\n (click)=\"clear()\"\n >\n <span class=\"truncate\">{{\n clearLabel()\n }}</span>\n </button>\n }\n @case ('item') {\n <button\n type=\"button\"\n role=\"option\"\n tabindex=\"-1\"\n class=\"text-dropdown-item-foreground ui-text-body-alt ui-select-option\"\n [attr.id]=\"row.id\"\n [attr.aria-selected]=\"row.selected\"\n [attr.data-active]=\"row.index === activeIndex() ? '' : null\"\n (mousedown)=\"$event.preventDefault()\"\n (mouseenter)=\"activeIndex.set(row.index)\"\n (click)=\"onItemClick(row.item)\"\n >\n @if (optionTemplate(); as template) {\n <span\n class=\"flex items-center gap-2 min-w-0 grow\"\n >\n <ng-container\n *ngTemplateOutlet=\"template; context: {\n $implicit: row.item,\n selected: row.selected,\n active: row.index === activeIndex()\n }\"\n />\n </span>\n } @else {\n <span class=\"truncate\">{{\n row.label\n }}</span>\n }\n\n @if (row.selected) {\n <ng-icon\n name=\"heroCheck\"\n class=\"size-4 text-primary-600! shrink-0\"\n strokeWidth=\"2.5\"\n />\n }\n </button>\n }\n @case ('create') {\n <button\n type=\"button\"\n role=\"option\"\n aria-selected=\"false\"\n tabindex=\"-1\"\n class=\"justify-start! text-primary-600 ui-text-body-alt ui-select-option\"\n [attr.id]=\"row.id\"\n [attr.data-active]=\"row.index === activeIndex() ? '' : null\"\n (mousedown)=\"$event.preventDefault()\"\n (mouseenter)=\"activeIndex.set(row.index)\"\n (click)=\"onCreate()\"\n >\n <ng-icon\n name=\"heroPlus\"\n class=\"size-4 shrink-0\"\n />\n <span class=\"truncate\">{{\n createLabel()(row.query)\n }}</span>\n </button>\n }\n }\n }\n\n @if (loading()) {\n <div class=\"px-3 py-2 text-muted-foreground ui-text-body-alt text-center\">\n Loading...\n </div>\n }\n\n @if (!loading() && items().length === 0 && !createQuery()) {\n <div class=\"px-3 py-2 text-muted-foreground ui-text-body-alt text-center\">\n No results\n </div>\n }\n </div>\n </ui-card>\n </div>\n }\n</ui-dropdown>\n","import { Observable, of } from 'rxjs';\n\n\nexport interface SelectDataSourceParameters {\n query: string;\n page: number;\n size: number;\n}\n\nexport interface SelectDataSourceContent<Model> {\n items: Model[];\n hasMore: boolean;\n}\n\nexport interface SelectDataSource<Model> {\n load(\n params: SelectDataSourceParameters\n ): Observable<SelectDataSourceContent<Model>>;\n}\n\nexport class SelectLocalDataSource<Model> implements SelectDataSource<Model> {\n constructor(\n private readonly items: Model[],\n private readonly search: (item: Model, query: string) => boolean\n ) {}\n\n load(\n params: SelectDataSourceParameters\n ): Observable<SelectDataSourceContent<Model>> {\n const query = params.query.trim();\n\n const filteredItems = query\n ? this.items.filter(item => this.search(item, query))\n : this.items;\n\n const start = params.page * params.size;\n const end = start + params.size;\n\n return of({\n items: filteredItems.slice(start, end),\n hasMore: end < filteredItems.length\n });\n }\n}\n\n// wraps any fetch function, so no specific backend is baked in here\nexport class SelectRemoteDataSource<Model> implements SelectDataSource<Model> {\n constructor(\n private readonly fetch: (\n params: SelectDataSourceParameters\n ) => Observable<SelectDataSourceContent<Model>>\n ) {}\n\n load(\n params: SelectDataSourceParameters\n ): Observable<SelectDataSourceContent<Model>> {\n return this.fetch(params);\n }\n}\n","export type SearchMode =\n | 'none'\n | 'inline'\n | 'dropdown';\n\n/** How a multiple select shows its selection when closed. */\nexport const SelectMultipleDisplays = ['text', 'tags'] as const;\n\n/** @see {@link SelectMultipleDisplays} */\nexport type SelectMultipleDisplay = typeof SelectMultipleDisplays[number];\n\n/** Context for a projected `#option` template. */\nexport interface SelectOptionContext<Model> {\n $implicit: Model;\n selected: boolean;\n active: boolean;\n}\n\n/** Context for a projected `#trigger` template, single select only. */\nexport interface SelectTriggerContext<Model> {\n $implicit: Model;\n}\n\n/** Context for a projected `#leading` template, inline search single select only. */\nexport interface SelectLeadingContext<Model> {\n $implicit: Model;\n}\n\n/** One line in the open list. Groups are headings, the rest can be picked. */\nexport type SelectRow<Model> =\n | { kind: 'group'; id: string; label: string; }\n | { kind: 'clear'; id: string; index: number; }\n | { kind: 'create'; id: string; index: number; query: string; }\n | {\n kind: 'item';\n id: string;\n index: number;\n item: Model;\n label: string;\n selected: boolean;\n };\n"],"mappings":";;;;;;;;;;;AA0DA,IAAI,SAAS;AAuBb,IAAa,oBAAb,MAAa,kBAAiB;CACjB,SAAS,OAAO,OAAM,GAAA,YAAA,CAAA,EAAA,WAAA,SAAA,CAAA,+BAAA,CAAA,CAAA;CACtB,YAAY,MAAiB,gBAAe,GAAA,YAAA,CAAA,EAAA,WAAA,YAAA,CAAA,+BAAA,CAAA,CAAA;CAC5C,iBAAiB,MACtB,oBACH,GAAA,YAAA,CAAA,EAAA,WAAA,iBAAA,CAAA,+BAAA,CAAA,CAAA;CAEQ,aAAa,MAAM,SAAmC,GAAA,YAAA,CAAA,EAAA,WAAA,aAAA,CAAA,+BAAA,CAAA,CAAA;CACtD,QAAQ,OAAgB,CAAA,GAAG,GAAA,YAAA,CAAA,EAAA,WAAA,QAAA,CAAA,+BAAA,CAAA,CAAA;CAE3B,cAAc,MAAc,oBAAmB,GAAA,YAAA,CAAA,EAAA,WAAA,cAAA,CAAA,+BAAA,CAAA,CAAA;CAG/C,KAAK,MAAc,IAAG,GAAA,YAAA,CAAA,EAAA,WAAA,KAAA,CAAA,+BAAA,CAAA,CAAA;CACtB,cAAc,MAAc,IAAG,GAAA,YAAA,CAAA,EAAA,WAAA,cAAA,CAAA,+BAAA,CAAA,CAAA;CAE/B,WAAW,MAAc,IAAG,GAAA,YAAA,CAAA,EAAA,WAAA,WAAA,CAAA,+BAAA,CAAA,CAAA;CAC5B,aAAa,MAAkB,QAAO,GAAA,YAAA,CAAA,EAAA,WAAA,aAAA,CAAA,+BAAA,CAAA,CAAA;CAGtC,WAAW,MAAM,OAAK;EAAA,GAAA,YAAA,EAAA,WAAA,WAAA,+BAAA,CAAA;EAAI,WAAW;CAAgB,CAAA;CAErD,kBAAkB,MAAuB,MAAK,GAAA,YAAA,CAAA,EAAA,WAAA,kBAAA,CAAA,+BAAA,CAAA,CAAA;CAG9C,YAAY,MAAM,OAAK;EAAA,GAAA,YAAA,EAAA,WAAA,YAAA,+BAAA,CAAA;EAAI,WAAW;CAAgB,CAAA;CACtD,aAAa,MAAc,QAAO,GAAA,YAAA,CAAA,EAAA,WAAA,aAAA,CAAA,+BAAA,CAAA,CAAA;CAMlC,YAAY,MAAM,OAAK;EAAA,GAAA,YAAA,EAAA,WAAA,YAAA,+BAAA,CAAA;EAAI,WAAW;CAAgB,CAAA;CACtD,cAAc,OAAiC,UACpD,WAAW,MAAK,IACnB,GAAA,YAAA,CAAA,EAAA,WAAA,cAAA,CAAA,+BAAA,CAAA,CAAA;CAGQ,UAAU,MAA+C,MAAK,GAAA,YAAA,CAAA,EAAA,WAAA,UAAA,CAAA,+BAAA,CAAA,CAAA;CAG9D,mBAAmB,MAAM,MAAI;EAAA,GAAA,YAAA,EAAA,WAAA,mBAAA,+BAAA,CAAA;EAAI,WAAW;CAAgB,CAAA;CAG5D,WAAW,MAAM,OAAK;EAAA,GAAA,YAAA,EAAA,WAAA,WAAA,+BAAA,CAAA;EAAI,WAAW;CAAgB,CAAA;CACrD,kBAAkB,MAA6B,QAAO,GAAA,YAAA,CAAA,EAAA,WAAA,kBAAA,CAAA,+BAAA,CAAA,CAAA;CAGtD,eAAe,MAAqB,MAAK,GAAA,YAAA,CAAA,EAAA,WAAA,eAAA,CAAA,+BAAA,CAAA,CAAA;CACzC,eAAe,OAAiC,UACrD,GAAG,MAAK,YACX,GAAA,YAAA,CAAA,EAAA,WAAA,eAAA,CAAA,+BAAA,CAAA,CAAA;CAEQ,cAAc,OAClB,GAAG,MAAM,MAAM,GACnB,GAAA,YAAA,CAAA,EAAA,WAAA,cAAA,CAAA,+BAAA,CAAA,CAAA;CAEQ,cAAc,OACnB,SAAQ,GAAG,QACd,GAAA,YAAA,CAAA,EAAA,WAAA,cAAA,CAAA,+BAAA,CAAA,CAAA;CAEQ,kBAAkB,OAAM;CAGxB,SAAS,OAAM;CAEf,eAAe,MAAoB,MAAK,GAAA,YAAA,CAAA,EAAA,WAAA,eAAA,CAAA,+BAAA,CAAA,CAAA;CACxC,gBAAgB,MAAe,CAAA,GAAG,GAAA,YAAA,CAAA,EAAA,WAAA,gBAAA,CAAA,+BAAA,CAAA,CAAA;CAClC,QAAQ,OAAO,IAAG,GAAA,YAAA,CAAA,EAAA,WAAA,QAAA,CAAA,+BAAA,CAAA,CAAA;CAClB,UAAU,OAAO,OAAM,GAAA,YAAA,CAAA,EAAA,WAAA,UAAA,CAAA,+BAAA,CAAA,CAAA;CACvB,UAAU,OAAO,MAAK,GAAA,YAAA,CAAA,EAAA,WAAA,UAAA,CAAA,+BAAA,CAAA,CAAA;CAEtB,iBAAiB,aAExB,UAAS,GAAA,YAAA,CAAA,EAAA,WAAA,iBAAA,CAAA,+BAAA,CAAA,CAAA;CACF,kBAAkB,aAEzB,WAAU,GAAA,YAAA,CAAA,EAAA,WAAA,kBAAA,CAAA,+BAAA,CAAA,CAAA;CAGH,kBAAkB,aAEzB,WAAU,GAAA,YAAA,CAAA,EAAA,WAAA,kBAAA,CAAA,+BAAA,CAAA,CAAA;CAGH,cAAc,OAAO,GAAE,GAAA,YAAA,CAAA,EAAA,WAAA,cAAA,CAAA,+BAAA,CAAA,CAAA;CAEvB,SAAS,aAAa;CAEtB,eAAe,eACpB,KAAK,SAAQ,IACP,KAAK,cAAa,CAAE,CAAC,SAAS,IAC9B,KAAK,aAAY,MAAO,MACjC,GAAA,YAAA,CAAA,EAAA,WAAA,eAAA,CAAA,+BAAA,CAAA,CAAA;CAEQ,eAAe,eAAc;EAClC,MAAM,UAAU,KAAK,YAAW;EAEhC,IAAI,CAAC,KAAK,SAAQ,GAAI;GAClB,MAAM,WAAW,KAAK,aAAY;GAElC,OAAO,aAAa,OAAO,QAAQ,QAAQ,IAAI,KAAK,YAAW;EACnE;EAEA,MAAM,WAAW,KAAK,cAAa;EACnC,MAAM,eAAe,KAAK,aAAY;EAEtC,IAAI,CAAC,SAAS,QACV,OAAO,KAAK,YAAW;EAG3B,OAAO,iBAAiB,QAAQ,SAAS,SAAS,eAC5C,KAAK,aAAY,CAAE,CAAC,SAAS,MAAM,IACnC,SAAS,IAAI,OAAO,CAAC,CAAC,KAAK,IAAI;CACzC,GAAE,GAAA,YAAA,CAAA,EAAA,WAAA,eAAA,CAAA,+BAAA,CAAA,CAAA;CAEO,UAAU,eACf,KAAK,SAAQ,IAAK,CAAC,KAAK,cAAa,CAAE,CAAC,SAAS,KAAK,aAAY,MAAO,MAC5E,GAAA,YAAA,CAAA,EAAA,WAAA,UAAA,CAAA,+BAAA,CAAA,CAAA;CAGQ,WAAW,eAChB,KAAK,SAAQ,KACb,KAAK,gBAAe,MAAO,UAC3B,KAAK,WAAU,MAAO,UACzB,GAAA,YAAA,CAAA,EAAA,WAAA,WAAA,CAAA,+BAAA,CAAA,CAAA;CAEQ,cAAc,eACnB,CAAC,CAAC,KAAK,gBAAe,KACtB,CAAC,KAAK,SAAQ,KACd,KAAK,aAAY,MAAO,MAC3B,GAAA,YAAA,CAAA,EAAA,WAAA,cAAA,CAAA,+BAAA,CAAA,CAAA;CAGQ,gBAAgB,eACrB,KAAK,OAAM,KAAM,KAAK,MAAK,MAAO,IACrC,GAAA,YAAA,CAAA,EAAA,WAAA,gBAAA,CAAA,+BAAA,CAAA,CAAA;CAGQ,cAAc,eAAc;EACjC,MAAM,QAAQ,KAAK,MAAK,CAAE,CAAC,KAAI;EAC/B,MAAM,UAAU,KAAK,YAAW;EAEhC,IAAI,CAAC,KAAK,UAAS,KAAM,CAAC,SAAS,KAAK,QAAO,GAC3C,OAAO;EAOX,OAJe,KAAK,MAAK,CAAE,CAAC,MAAK,SAC7B,QAAQ,IAAI,CAAC,CAAC,YAAW,MAAO,MAAM,YAAW,CAG9C,IAAS,OAAO;CAC3B,GAAE,GAAA,YAAA,CAAA,EAAA,WAAA,cAAA,CAAA,+BAAA,CAAA,CAAA;CAEO,OAAO,eAAkC;EAC9C,MAAM,OAA2B,CAAA;EACjC,MAAM,UAAU,KAAK,QAAO;EAC5B,MAAM,UAAU,KAAK,YAAW;EAChC,MAAM,cAAc,KAAK,YAAW;EAEpC,IAAI,QAAQ;EACZ,IAAI;EAEJ,IAAI,KAAK,UAAS,KAAM,KAAK,aAAY,GACrC,KAAK,KAAK;GAAE,MAAM;GAAS,IAAI,KAAK,MAAM,KAAK;GAAG,OAAO;EAAO,CAAE;EAGtE,KAAK,MAAM,QAAQ,KAAK,MAAK,GAAI;GAC7B,IAAI,SAAS;IACT,MAAM,OAAO,QAAQ,IAAI;IAEzB,IAAI,SAAS,SAAS,MAClB,KAAK,KAAK;KACN,MAAM;KACN,IAAI,GAAG,KAAK,OAAM,SAAU,KAAK;KACjC,OAAO;IACV,CAAA;IAGL,QAAQ;GACZ;GAEA,KAAK,KAAK;IACN,MAAM;IACN,IAAI,KAAK,MAAM,KAAK;IACpB,OAAO;IACP;IACA,OAAO,QAAQ,IAAI;IACnB,UAAU,KAAK,WAAW,IAAI;GACjC,CAAA;EACL;EAEA,IAAI,aACA,KAAK,KAAK;GACN,MAAM;GACN,IAAI,KAAK,MAAM,KAAK;GACpB;GACA,OAAO;EACV,CAAA;EAGL,OAAO;CACX,GAAE,GAAA,YAAA,CAAA,EAAA,WAAA,OAAA,CAAA,+BAAA,CAAA,CAAA;CAEe,WAAW,eACxB,KAAK,KAAI,CAAE,CAAC,QAAO,QAAO,IAAI,SAAS,OAAO,GACjD,GAAA,YAAA,CAAA,EAAA,WAAA,WAAA,CAAA,+BAAA,CAAA,CAAA;CAEQ,WAAW,eAChB,KAAK,OAAM,IAAK,KAAK,SAAQ,CAAE,CAAC,KAAK,YAAW,EAAG,EAAE,MAAM,OAAO,MACrE,GAAA,YAAA,CAAA,EAAA,WAAA,WAAA,CAAA,+BAAA,CAAA,CAAA;CAEO,OAAO;CAGE,QAAQ,IAAI,QAAO;CAEnB,OAAO,OAAgC,UAAU;CACjD,WAAW,OAAO,QAAQ;CAC1B,aAAa,OAAO,UAAU;CAC9B,MAAM,OAAO,iBAAiB;CAE/C,cAAA;EAEI,aAAY;GACR,KAAK,WAAU;GACf,gBAAgB,KAAK,cAAa,CAAE;EACxC,CAAC;EAGD,aAAY;GACR,IAAI,CAAC,KAAK,OAAM,GACZ;GAGJ,gBAAe;IACX,MAAM,WAAW,KAAK,SAAQ,CAAE,CAAC,WAAU,QACvC,IAAI,SAAS,UAAU,IAAI,QAAQ;IAGvC,KAAK,YAAY,IACb,KAAK,iBAAgB,KAAM,YAAY,IAAI,WAAW,CAAC;IAG3D,sBAAqB;KACjB,IAAI,KAAK,iBAAgB,GACrB,KAAK,qBAAoB;KAG7B,IAAI,KAAK,WAAU,MAAO,YACtB,KAAK,YAAW,CAAE,EAAE,MAAK;IAEjC,GAAG,EAAE,UAAU,KAAK,SAAQ,CAAE;GAClC,CAAC;EACL,CAAC;EAGD,aAAa,KAAK,KAAK,CAAC,CAAC,KACrB,aAAa,GAAG,GAChB,KAAK,CAAC,GACN,mBAAmB,KAAK,UAAU,CAAC,CACtC,CAAC,gBAAgB,KAAK,cAAa,CAAE;EAGtC,KAAK,MAAM,KACP,gBAAgB,KAAK,UAAS,CAAE,GAChC,mBAAmB,KAAK,UAAU,CAAC,CACtC,CAAC,WAAU,WAAU,KAAK,YAAY,MAAM,CAAC;CAClD;CAEQ,YAAS;EACb,KAAK,QAAQ,IAAI,IAAI;EAQrB,OANgB,KAAK,WAAU,CAAE,CAAC,KAAK;GACnC,OAAO,KAAK,MAAK;GACjB,MAAM,KAAK;GACX,MAAM,KAAK,SAAQ;EACtB,CAEM,CAAA,CAAQ,KAAK,iBAAiB,GAAG,IAAI,CAAC,CAAC;CAClD;CAEQ,YAAY,QAA6C;EAC7D,KAAK,QAAQ,IAAI,KAAK;EAEtB,IAAI,QAAQ;GACR,KAAK,MAAM,QAAO,UAAS,CAAC,GAAG,OAAO,GAAG,OAAO,KAAK,CAAC;GACtD,KAAK,QAAQ,IAAI,OAAO,OAAO;EACnC;EAEA,KAAK,IAAI,aAAY;CACzB;CAEA,OAAI;EACA,IAAI,CAAC,KAAK,SAAQ,GACd,KAAK,OAAO,IAAI,IAAI;CAE5B;CAEA,SAAM;EACF,IAAI,KAAK,OAAM,GACX,KAAK,OAAO,IAAI,KAAK;OAErB,KAAK,KAAI;CAEjB;CAEA,OAAO,MAAW;EACd,KAAK,aAAa,IAAI,IAAI;EAC1B,KAAK,gBAAgB,KAAK,IAAI;CAClC;CAEA,WAAW,MAAW;EAClB,MAAM,UAAU,KAAK,YAAW;EAEhC,IAAI,SAAS,MACT,OAAO;EAGX,IAAI,KAAK,SAAQ,GACb,OAAO,KAAK,cAAa,CAAE,CAAC,MAAK,aAC7B,QAAQ,UAAU,IAAI,CAAC;EAI/B,MAAM,WAAW,KAAK,aAAY;EAElC,OAAO,aAAa,QAAQ,QAAQ,UAAU,IAAI;CACtD;CAEA,WAAW,MAAW;EAClB,MAAM,UAAU,KAAK,YAAW;EAEhC,KAAK,cAAc,QAAO,aACtB,KAAK,WAAW,IAAI,IACd,SAAS,QAAO,aAAY,CAAC,QAAQ,UAAU,IAAI,CAAC,IACpD,CAAC,GAAG,UAAU,IAAI,CAAC;CAEjC;CAEA,WAAW,MAAW;EAClB,MAAM,UAAU,KAAK,YAAW;EAEhC,KAAK,cAAc,QAAO,aACtB,SAAS,QAAO,aAAY,CAAC,QAAQ,UAAU,IAAI,CAAC,CAAC;CAE7D;CAEA,QAAK;EACD,IAAI,KAAK,SAAQ,GACb,KAAK,cAAc,IAAI,CAAA,CAAE;OACtB;GACH,KAAK,aAAa,IAAI,IAAI;GAC1B,KAAK,gBAAgB,KAAK,IAAI;EAClC;EAEA,KAAK,OAAO,IAAI,KAAK;EACrB,KAAK,aAAY;EAEjB,IAAI,KAAK,WAAU,MAAO,UACtB,KAAK,MAAM,IAAI,EAAE;CAEzB;CAEA,YAAY,MAAW;EAEnB,IAAI,KAAK,SAAQ,GAAI;GACjB,KAAK,WAAW,IAAI;GACpB;EACJ;EAEA,KAAK,OAAO,IAAI;EAChB,KAAK,OAAO,IAAI,KAAK;EACrB,KAAK,aAAY;EAKjB,IAAI,KAAK,WAAU,MAAO,UACtB,KAAK,MAAM,IAAI,EAAE;CAEzB;CAEA,WAAQ;EACJ,MAAM,QAAQ,KAAK,YAAW;EAE9B,IAAI,CAAC,OACD;EAGJ,KAAK,OAAO,KAAK,KAAK;EACtB,KAAK,MAAM,IAAI,EAAE;EAEjB,IAAI,CAAC,KAAK,SAAQ,GAAI;GAClB,KAAK,OAAO,IAAI,KAAK;GACrB,KAAK,aAAY;EACrB;CACJ;CAEA,UAAU,OAAoB;EAC1B,MAAM,QAAQ,KAAK,SAAQ,CAAE,CAAC;EAE9B,MAAM,cAAc,MAAM,QAAQ,OAAO,KAAK,WAAU,MAAO;EAE/D,QAAQ,MAAM,KAAd;GACI,KAAK;GACL,KAAK;IACD,MAAM,eAAc;IAEpB,IAAI,CAAC,KAAK,OAAM,GAAI;KAChB,KAAK,KAAI;KACT;IACJ;IAEA,KAAK,WAAW,MAAM,QAAQ,cAAc,IAAI,IAAI,KAAK;IACzD;GACJ,KAAK;GACL,KAAK;IACD,IAAI,KAAK,OAAM,KAAM,SAAS,KAAK,WAAU,MAAO,QAAQ;KACxD,MAAM,eAAc;KACpB,KAAK,UAAU,MAAM,QAAQ,SAAS,IAAI,QAAQ,CAAC;IACvD;IACA;GACJ,KAAK;GACL,KAAK;IACD,IAAI,MAAM,QAAQ,OAAO,CAAC,aACtB;IAGJ,MAAM,eAAc;IAEpB,IAAI,CAAC,KAAK,OAAM,GACZ,KAAK,KAAI;SAET,KAAK,WAAU;IAEnB;GACJ,KAAK;IAED,KAAK,aAAY;IACjB;EACR;CACJ;CAEA,WAAW,OAAiB;EACxB,MAAM,OAAO,MAAM;EAEnB,IAAI,KAAK,eAAc,MAAO,QAC1B;EAIJ,IACI,EAAE,gBAAgB,SAClB,CAAC,KAAK,KAAK,cAAc,SAAS,IAAI,GAEtC,KAAK,OAAO,IAAI,KAAK;CAE7B;CAEA,UAAU,OAAa;EACnB,KAAK,YAAY,IAAI,KAAK;EAE1B,sBAAsB,KAAK,qBAAoB,GAAI,EAC/C,UAAU,KAAK,SAClB,CAAA;CACL;CAEA,gBAAa;EACT,KAAK,OAAO;EACZ,KAAK,MAAM,IAAI,CAAA,CAAE;EACjB,KAAK,QAAQ,IAAI,IAAI;EAErB,KAAK,MAAM,KAAI;CACnB;CAEA,eAAY;EACR,IAAI,KAAK,QAAO,KAAM,CAAC,KAAK,QAAO,GAC/B;EAGJ,KAAK;EACL,KAAK,MAAM,KAAI;CACnB;CAEA,cAAc,OAAa;EAGvB,KAAK,MAAM,IAAI,KAAK;EACpB,KAAK,YAAY,IAAI,CAAC;EACtB,KAAK,KAAI;CACb;CAEA,SAAS,iBAA4B;EAKjC,IAJwB,gBAAgB,eAClC,gBAAgB,YAChB,gBAAgB,eAEA,IAClB,KAAK,aAAY;CAEzB;CAEQ,aAAU;EACd,MAAM,MAAM,KAAK,SAAQ,CAAE,CAAC,KAAK,YAAW;EAE5C,IAAI,CAAC,KACD;EAGJ,IAAI,IAAI,SAAS,SACb,KAAK,MAAK;OACP,IAAI,IAAI,SAAS,UACpB,KAAK,SAAQ;OACV,IAAI,IAAI,SAAS,QACpB,KAAK,YAAY,IAAI,IAAI;CAEjC;CAEQ,WAAW,MAAc,OAAa;EAC1C,IAAI,OACA,KAAK,WAAW,KAAK,YAAW,IAAK,OAAO,SAAS,KAAK;CAElE;CAEQ,uBAAoB;EACxB,MAAM,KAAK,KAAK,SAAQ;EAExB,IAAI,IACA,KAAK,KAAK,cACL,cAAc,IAAI,IAAI,CAAC,EACtB,eAAe,EAAE,OAAO,UAAS,CAAE;CAEjD;CAEQ,eAAY;EAKhB,CAJgB,KAAK,WAAU,MAAO,WAChC,KAAK,YAAW,IAChB,KAAK,KAAK,cAAc,cAA2B,YAAY,EAErE,EAAS,MAAK;CAClB;CAGQ,cAAW;EACf,OAAO,KAAK,KAAK,cAAc,cAAc,gBAAgB;CACjE;CAEQ,MAAM,OAAa;EACvB,OAAO,GAAG,KAAK,OAAM,GAAI;CAC7B;CAtiBS,OAAA,OAAA,GAAA,mBAAA;EAAA,YAAA;EAAA,SAAA;EAAA,UAAA;EAAA,MAAA;EAAiB,MAAA,CAAA;EAAA,QAAA,GAAA,gBAAA;CAAA,CAAA;CAAjB,OAAA,OAAA,GAAA,qBAAA;EAAA,YAAA;EAAA,SAAA;EAAA,MAAA;EAAiB,cAAA;EAAA,UAAA;EAAA,QAAA;GAAA,WAAA;IAAA,mBAAA;IAAA,YAAA;IAAA,UAAA;IAAA,YAAA;IAAA,mBAAA;GAAA;GAAA,gBAAA;IAAA,mBAAA;IAAA,YAAA;IAAA,UAAA;IAAA,YAAA;IAAA,mBAAA;GAAA;GAAA,YAAA;IAAA,mBAAA;IAAA,YAAA;IAAA,UAAA;IAAA,YAAA;IAAA,mBAAA;GAAA;GAAA,aAAA;IAAA,mBAAA;IAAA,YAAA;IAAA,UAAA;IAAA,YAAA;IAAA,mBAAA;GAAA;GAAA,IAAA;IAAA,mBAAA;IAAA,YAAA;IAAA,UAAA;IAAA,YAAA;IAAA,mBAAA;GAAA;GAAA,aAAA;IAAA,mBAAA;IAAA,YAAA;IAAA,UAAA;IAAA,YAAA;IAAA,mBAAA;GAAA;GAAA,UAAA;IAAA,mBAAA;IAAA,YAAA;IAAA,UAAA;IAAA,YAAA;IAAA,mBAAA;GAAA;GAAA,YAAA;IAAA,mBAAA;IAAA,YAAA;IAAA,UAAA;IAAA,YAAA;IAAA,mBAAA;GAAA;GAAA,UAAA;IAAA,mBAAA;IAAA,YAAA;IAAA,UAAA;IAAA,YAAA;IAAA,mBAAA;GAAA;GAAA,iBAAA;IAAA,mBAAA;IAAA,YAAA;IAAA,UAAA;IAAA,YAAA;IAAA,mBAAA;GAAA;GAAA,WAAA;IAAA,mBAAA;IAAA,YAAA;IAAA,UAAA;IAAA,YAAA;IAAA,mBAAA;GAAA;GAAA,YAAA;IAAA,mBAAA;IAAA,YAAA;IAAA,UAAA;IAAA,YAAA;IAAA,mBAAA;GAAA;GAAA,WAAA;IAAA,mBAAA;IAAA,YAAA;IAAA,UAAA;IAAA,YAAA;IAAA,mBAAA;GAAA;GAAA,aAAA;IAAA,mBAAA;IAAA,YAAA;IAAA,UAAA;IAAA,YAAA;IAAA,mBAAA;GAAA;GAAA,SAAA;IAAA,mBAAA;IAAA,YAAA;IAAA,UAAA;IAAA,YAAA;IAAA,mBAAA;GAAA;GAAA,kBAAA;IAAA,mBAAA;IAAA,YAAA;IAAA,UAAA;IAAA,YAAA;IAAA,mBAAA;GAAA;GAAA,UAAA;IAAA,mBAAA;IAAA,YAAA;IAAA,UAAA;IAAA,YAAA;IAAA,mBAAA;GAAA;GAAA,iBAAA;IAAA,mBAAA;IAAA,YAAA;IAAA,UAAA;IAAA,YAAA;IAAA,mBAAA;GAAA;GAAA,cAAA;IAAA,mBAAA;IAAA,YAAA;IAAA,UAAA;IAAA,YAAA;IAAA,mBAAA;GAAA;GAAA,cAAA;IAAA,mBAAA;IAAA,YAAA;IAAA,UAAA;IAAA,YAAA;IAAA,mBAAA;GAAA;GAAA,aAAA;IAAA,mBAAA;IAAA,YAAA;IAAA,UAAA;IAAA,YAAA;IAAA,mBAAA;GAAA;GAAA,aAAA;IAAA,mBAAA;IAAA,YAAA;IAAA,UAAA;IAAA,YAAA;IAAA,mBAAA;GAAA;GAAA,cAAA;IAAA,mBAAA;IAAA,YAAA;IAAA,UAAA;IAAA,YAAA;IAAA,mBAAA;GAAA;GAAA,eAAA;IAAA,mBAAA;IAAA,YAAA;IAAA,UAAA;IAAA,YAAA;IAAA,mBAAA;GAAA;EAAA;EAAA,SAAA;GAAA,iBAAA;GAAA,iBAAA;GAAA,QAAA;GAAA,cAAA;GAAA,eAAA;EAAA;EAAA,MAAA;GAAA,WAAA,EAAA,YAAA,qBAAA;GAAA,YAAA,EAAA,WAAA,OAAA;EAAA;EAAA,WAPf,CAAC,aAAa;GACrB;GACA;GACA;GACA;EACH,CAAA,CAAC;EAAC,SAAA;GAAA;IAAA,cAAA;IAAA,OAAA;IAAA,WAAA,CAAA,QAAA;IAAA,aAAA;IAAA,UAAA;GAAA;GAAA;IAAA,cAAA;IAAA,OAAA;IAAA,WAAA,CAAA,SAAA;IAAA,aAAA;IAAA,UAAA;GAAA;GAAA;IAAA,cAAA;IAAA,OAAA;IAAA,WAAA,CAAA,SAAA;IAAA,aAAA;IAAA,UAAA;GAAA;EAAA;EAAA,UAAA;EAAA,UC/EP;EA0RA,QAAA,CAAA,k3TAAA;EAAA,cAAA;GAAA;IAAA,MAAA;IAAA,MDzNQ;IAAmB,UAAA;IAAA,QAAA;KAAA;KAAA;KAAA;KAAA;KAAA;KAAA;IAAA;IAAA,UAAA,CAAA,YAAA;GAAA;GAAA;IAAA,MAAA;IAAA,MACnB;IAAmB,UAAA;GAAA;GAAA;IAAA,MAAA;IAAA,MACnB;IAAgB,UAAA;IAAA,QAAA;KAAA;KAAA;KAAA;KAAA;KAAA;KAAA;KAAA;KAAA;KAAA;KAAA;KAAA;KAAA;KAAA;KAAA;KAAA;KAAA;KAAA;KAAA;KAAA;KAAA;KAAA;KAAA;KAAA;KAAA;KAAA;KAAA;KAAA;KAAA;KAAA;KAAA;IAAA;IAAA,SAAA;KAAA;KAAA;KAAA;KAAA;IAAA;GAAA;GAAA;IAAA,MAAA;IAAA,MAChB;IAAgB,UAAA;IAAA,QAAA;KAAA;KAAA;KAAA;IAAA;GAAA;GAAA;IAAA,MAAA;IAAA,MAChB;IAAe,UAAA;IAAA,QAAA,CAAA,QAAA;GAAA;GAAA;IAAA,MAAA;IAAA,MACf;IAAM,UAAA;IAAA,QAAA;KAAA;KAAA;KAAA;KAAA;KAAA;IAAA;GAAA;GAAA;IAAA,MAAA;IAAA,MACN;IAAgB,UAAA;IAAA,QAAA;KAAA;KAAA;KAAA;IAAA;GAAA;EAAA;CAAA,CAAA;;AAUX,GAAA,yBAAA;CAAA,YAAA;CAAA,SAAA;CAAA,UAAA;CAAA,MAAA;CAAiB,YAAA,CAAA;EArB7B,MAAA;EACa,MAAA,CAAA;GAAA,UAAA;GAAW,SAGZ;IACL;IACA;IACA;IACA;IACA;IACA;IACA;GACH;GAAA,MACK;IAAE,aAAa;IAAQ,cAAc;GAAoB;GAAE,WACtD,CAAC,aAAa;IACrB;IACA;IACA;IACA;GACH,CAAA,CAAC;GAAC,UAAA;GAAA,QAAA,CAAA,k3TAAA;EAAA,CAAA;CA4ED,CAAA;CAAA,sBAAA,CAAA;CAAA,gBAAA;EAAA,WAAA,CAAA;GAAA,MAAA,GAAA;GAAA,MAAA,CAAA;IAAA,UAAA;IAAA,OAAA;IAAA,UAAA;GAAA,CAAA;EAAA,CAAA;EAAA,gBAAA,CAAA;GAAA,MAAA,GAAA;GAAA,MAAA,CAAA;IAAA,UAAA;IAAA,OAAA;IAAA,UAAA;GAAA,CAAA;EAAA,CAAA;EAAA,YAAA,CAAA;GAAA,MAAA,GAAA;GAAA,MAAA,CAAA;IAAA,UAAA;IAAA,OAAA;IAAA,UAAA;GAAA,CAAA;EAAA,CAAA;EAAA,aAAA,CAAA;GAAA,MAAA,GAAA;GAAA,MAAA,CAAA;IAAA,UAAA;IAAA,OAAA;IAAA,UAAA;GAAA,CAAA;EAAA,CAAA;EAAA,IAAA,CAAA;GAAA,MAAA,GAAA;GAAA,MAAA,CAAA;IAAA,UAAA;IAAA,OAAA;IAAA,UAAA;GAAA,CAAA;EAAA,CAAA;EAAA,aAAA,CAAA;GAAA,MAAA,GAAA;GAAA,MAAA,CAAA;IAAA,UAAA;IAAA,OAAA;IAAA,UAAA;GAAA,CAAA;EAAA,CAAA;EAAA,UAAA,CAAA;GAAA,MAAA,GAAA;GAAA,MAAA,CAAA;IAAA,UAAA;IAAA,OAAA;IAAA,UAAA;GAAA,CAAA;EAAA,CAAA;EAAA,YAAA,CAAA;GAAA,MAAA,GAAA;GAAA,MAAA,CAAA;IAAA,UAAA;IAAA,OAAA;IAAA,UAAA;GAAA,CAAA;EAAA,CAAA;EAAA,UAAA,CAAA;GAAA,MAAA,GAAA;GAAA,MAAA,CAAA;IAAA,UAAA;IAAA,OAAA;IAAA,UAAA;GAAA,CAAA;EAAA,CAAA;EAAA,iBAAA,CAAA;GAAA,MAAA,GAAA;GAAA,MAAA,CAAA;IAAA,UAAA;IAAA,OAAA;IAAA,UAAA;GAAA,CAAA;EAAA,GAAA;GAAA,MAAA,GAAA;GAAA,MAAA,CAAA,uBAAA;EAAA,CAAA;EAAA,WAAA,CAAA;GAAA,MAAA,GAAA;GAAA,MAAA,CAAA;IAAA,UAAA;IAAA,OAAA;IAAA,UAAA;GAAA,CAAA;EAAA,CAAA;EAAA,YAAA,CAAA;GAAA,MAAA,GAAA;GAAA,MAAA,CAAA;IAAA,UAAA;IAAA,OAAA;IAAA,UAAA;GAAA,CAAA;EAAA,CAAA;EAAA,WAAA,CAAA;GAAA,MAAA,GAAA;GAAA,MAAA,CAAA;IAAA,UAAA;IAAA,OAAA;IAAA,UAAA;GAAA,CAAA;EAAA,CAAA;EAAA,aAAA,CAAA;GAAA,MAAA,GAAA;GAAA,MAAA,CAAA;IAAA,UAAA;IAAA,OAAA;IAAA,UAAA;GAAA,CAAA;EAAA,CAAA;EAAA,SAAA,CAAA;GAAA,MAAA,GAAA;GAAA,MAAA,CAAA;IAAA,UAAA;IAAA,OAAA;IAAA,UAAA;GAAA,CAAA;EAAA,CAAA;EAAA,kBAAA,CAAA;GAAA,MAAA,GAAA;GAAA,MAAA,CAAA;IAAA,UAAA;IAAA,OAAA;IAAA,UAAA;GAAA,CAAA;EAAA,CAAA;EAAA,UAAA,CAAA;GAAA,MAAA,GAAA;GAAA,MAAA,CAAA;IAAA,UAAA;IAAA,OAAA;IAAA,UAAA;GAAA,CAAA;EAAA,CAAA;EAAA,iBAAA,CAAA;GAAA,MAAA,GAAA;GAAA,MAAA,CAAA;IAAA,UAAA;IAAA,OAAA;IAAA,UAAA;GAAA,CAAA;EAAA,CAAA;EAAA,cAAA,CAAA;GAAA,MAAA,GAAA;GAAA,MAAA,CAAA;IAAA,UAAA;IAAA,OAAA;IAAA,UAAA;GAAA,CAAA;EAAA,CAAA;EAAA,cAAA,CAAA;GAAA,MAAA,GAAA;GAAA,MAAA,CAAA;IAAA,UAAA;IAAA,OAAA;IAAA,UAAA;GAAA,CAAA;EAAA,CAAA;EAAA,aAAA,CAAA;GAAA,MAAA,GAAA;GAAA,MAAA,CAAA;IAAA,UAAA;IAAA,OAAA;IAAA,UAAA;GAAA,CAAA;EAAA,CAAA;EAAA,aAAA,CAAA;GAAA,MAAA,GAAA;GAAA,MAAA,CAAA;IAAA,UAAA;IAAA,OAAA;IAAA,UAAA;GAAA,CAAA;EAAA,CAAA;EAAA,iBAAA,CAAA;GAAA,MAAA,GAAA;GAAA,MAAA,CAAA,iBAAA;EAAA,CAAA;EAAA,QAAA,CAAA;GAAA,MAAA,GAAA;GAAA,MAAA,CAAA,QAAA;EAAA,CAAA;EAAA,cAAA,CAAA;GAAA,MAAA,GAAA;GAAA,MAAA,CAAA;IAAA,UAAA;IAAA,OAAA;IAAA,UAAA;GAAA,CAAA;EAAA,GAAA;GAAA,MAAA,GAAA;GAAA,MAAA,CAAA,oBAAA;EAAA,CAAA;EAAA,eAAA,CAAA;GAAA,MAAA,GAAA;GAAA,MAAA,CAAA;IAAA,UAAA;IAAA,OAAA;IAAA,UAAA;GAAA,CAAA;EAAA,GAAA;GAAA,MAAA,GAAA;GAAA,MAAA,CAAA,qBAAA;EAAA,CAAA;EAAA,gBAAA,CAAA;GAAA,MAAA,GAAA;GAAA,MAAA,CAAA,UAAQ,EAAA,UAAA,KAAA,CAAA;EAAA,CAAA;EAAA,iBAAA,CAAA;GAAA,MAAA,GAAA;GAAA,MAAA,CAGR,WAAS,EAAA,UAAA,KAAA,CAAA;EAAA,CAAA;EAAA,iBAAA,CAAA;GAAA,MAAA,GAAA;GAAA,MAAA,CAKT,WAAS,EAAA,UAAA,KAAA,CAAA;EAAA,CAAA;CAAA;AAAA,CAAA;AE/If,IAAa,wBAAb,MAAkC;CAET;CACA;CAFrB,YACqB,OACA,QAA+C;EAD/C,KAAA,QAAA;EACA,KAAA,SAAA;CAClB;CAEH,KACI,QAAkC;EAElC,MAAM,QAAQ,OAAO,MAAM,KAAI;EAE/B,MAAM,gBAAgB,QAChB,KAAK,MAAM,QAAO,SAAQ,KAAK,OAAO,MAAM,KAAK,CAAC,IAClD,KAAK;EAEX,MAAM,QAAQ,OAAO,OAAO,OAAO;EACnC,MAAM,MAAM,QAAQ,OAAO;EAE3B,OAAO,GAAG;GACN,OAAO,cAAc,MAAM,OAAO,GAAG;GACrC,SAAS,MAAM,cAAc;EAChC,CAAA;CACL;AACH;AAGD,IAAa,yBAAb,MAAmC;CAEV;CADrB,YACqB,OAE8B;EAF9B,KAAA,QAAA;CAGlB;CAEH,KACI,QAAkC;EAElC,OAAO,KAAK,MAAM,MAAM;CAC5B;AACH;ACpDD,MAAa,yBAAyB,CAAC,QAAQ,MAAM"}
@@ -0,0 +1,60 @@
1
+ import * as i0 from "@angular/core";
2
+ import { Component, computed, inject, input } from "@angular/core";
3
+ import { UiSidebarComponent } from "@area8975/ui/sidebar";
4
+ let nextId = 0;
5
+ var UiSidebarGroupComponent = class UiSidebarGroupComponent {
6
+ sidebar = inject(UiSidebarComponent, { optional: true });
7
+ label = input.required(...ngDevMode ? [{ debugName: "label" }] : /* istanbul ignore next */ []);
8
+ labelId = `ui-sidebar-group-${nextId++}`;
9
+ isCollapsed = computed(() => this.sidebar?.isCollapsed() ?? false, ...ngDevMode ? [{ debugName: "isCollapsed" }] : /* istanbul ignore next */ []);
10
+ static ɵfac = i0.ɵɵngDeclareFactory({
11
+ minVersion: "12.0.0",
12
+ version: "22.2.1",
13
+ ngImport: i0,
14
+ type: UiSidebarGroupComponent,
15
+ deps: [],
16
+ target: i0.ɵɵFactoryTarget.Component
17
+ });
18
+ static ɵcmp = i0.ɵɵngDeclareComponent({
19
+ minVersion: "17.0.0",
20
+ version: "22.2.1",
21
+ type: UiSidebarGroupComponent,
22
+ isStandalone: true,
23
+ selector: "ui-sidebar-group",
24
+ inputs: { label: {
25
+ classPropertyName: "label",
26
+ publicName: "label",
27
+ isSignal: true,
28
+ isRequired: true,
29
+ transformFunction: null
30
+ } },
31
+ ngImport: i0,
32
+ template: "@if (isCollapsed()) {\n <div class=\"ui-sidebar-group-divider\" aria-hidden=\"true\"></div>\n} @else {\n <span class=\"ui-sidebar-group-label ui-text-caption\" [id]=\"labelId\">{{ label() }}</span>\n}\n\n<div\n class=\"ui-sidebar-group-items\"\n role=\"group\"\n [attr.aria-labelledby]=\"isCollapsed() ? null : labelId\"\n [attr.aria-label]=\"isCollapsed() ? label() : null\"\n>\n <ng-content />\n</div>\n",
33
+ styles: ["@layer properties;:host{display:flex;flex-direction:column;align-self:stretch}:host(:not(:first-child)){margin-top:calc(var(--spacing, .25rem) * 4)}.ui-sidebar-group-label{overflow:hidden;text-overflow:ellipsis;white-space:nowrap;padding-inline:calc(var(--spacing, .25rem) * 2.5);padding-bottom:calc(var(--spacing, .25rem) * 1.5);--tw-font-weight: var(--font-weight-medium, 500);font-weight:var(--font-weight-medium, 500);--tw-tracking: var(--tracking-wide, .025em);letter-spacing:var(--tracking-wide, .025em);color:var(--muted-foreground-1);text-transform:uppercase}.ui-sidebar-group-divider{margin-inline:calc(var(--spacing, .25rem) * 2);margin-bottom:calc(var(--spacing, .25rem) * 2);border-top-style:var(--tw-border-style);border-top-width:1px;border-color:var(--sidebar-line)}:host(:first-child) .ui-sidebar-group-divider{display:none}.ui-sidebar-group-items{display:flex;flex-direction:column;row-gap:var(--spacing, .25rem)}@property --tw-font-weight{syntax: \"*\"; inherits: false;}@property --tw-tracking{syntax: \"*\"; inherits: false;}@property --tw-border-style{syntax: \"*\"; inherits: false; initial-value: solid;}@layer properties{@supports ((-webkit-hyphens: none) and (not (margin-trim: inline))) or ((-moz-orient: inline) and (not (color:rgb(from red r g b)))){*,:before,:after,::backdrop{--tw-font-weight: initial;--tw-tracking: initial;--tw-border-style: solid}}}\n/*! tailwindcss v4.3.3 | MIT License | https://tailwindcss.com */\n"]
34
+ });
35
+ };
36
+ i0.ɵɵngDeclareClassMetadata({
37
+ minVersion: "12.0.0",
38
+ version: "22.2.1",
39
+ ngImport: i0,
40
+ type: UiSidebarGroupComponent,
41
+ decorators: [{
42
+ type: Component,
43
+ args: [{
44
+ selector: "ui-sidebar-group",
45
+ template: "@if (isCollapsed()) {\n <div class=\"ui-sidebar-group-divider\" aria-hidden=\"true\"></div>\n} @else {\n <span class=\"ui-sidebar-group-label ui-text-caption\" [id]=\"labelId\">{{ label() }}</span>\n}\n\n<div\n class=\"ui-sidebar-group-items\"\n role=\"group\"\n [attr.aria-labelledby]=\"isCollapsed() ? null : labelId\"\n [attr.aria-label]=\"isCollapsed() ? label() : null\"\n>\n <ng-content />\n</div>\n",
46
+ styles: ["@layer properties;:host{display:flex;flex-direction:column;align-self:stretch}:host(:not(:first-child)){margin-top:calc(var(--spacing, .25rem) * 4)}.ui-sidebar-group-label{overflow:hidden;text-overflow:ellipsis;white-space:nowrap;padding-inline:calc(var(--spacing, .25rem) * 2.5);padding-bottom:calc(var(--spacing, .25rem) * 1.5);--tw-font-weight: var(--font-weight-medium, 500);font-weight:var(--font-weight-medium, 500);--tw-tracking: var(--tracking-wide, .025em);letter-spacing:var(--tracking-wide, .025em);color:var(--muted-foreground-1);text-transform:uppercase}.ui-sidebar-group-divider{margin-inline:calc(var(--spacing, .25rem) * 2);margin-bottom:calc(var(--spacing, .25rem) * 2);border-top-style:var(--tw-border-style);border-top-width:1px;border-color:var(--sidebar-line)}:host(:first-child) .ui-sidebar-group-divider{display:none}.ui-sidebar-group-items{display:flex;flex-direction:column;row-gap:var(--spacing, .25rem)}@property --tw-font-weight{syntax: \"*\"; inherits: false;}@property --tw-tracking{syntax: \"*\"; inherits: false;}@property --tw-border-style{syntax: \"*\"; inherits: false; initial-value: solid;}@layer properties{@supports ((-webkit-hyphens: none) and (not (margin-trim: inline))) or ((-moz-orient: inline) and (not (color:rgb(from red r g b)))){*,:before,:after,::backdrop{--tw-font-weight: initial;--tw-tracking: initial;--tw-border-style: solid}}}\n/*! tailwindcss v4.3.3 | MIT License | https://tailwindcss.com */\n"]
47
+ }]
48
+ }],
49
+ propDecorators: { label: [{
50
+ type: i0.Input,
51
+ args: [{
52
+ isSignal: true,
53
+ alias: "label",
54
+ required: true
55
+ }]
56
+ }] }
57
+ });
58
+ export { UiSidebarGroupComponent };
59
+
60
+ //# sourceMappingURL=area8975-ui-sidebar-group.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"area8975-ui-sidebar-group.mjs","names":[],"sources":["../../../projects/ui/sidebar-group/sidebar-group.component.ts","../../../projects/ui/sidebar-group/sidebar-group.component.html"],"sourcesContent":["import { Component, computed, inject, input } from '@angular/core';\n\nimport { UiSidebarComponent } from '@area8975/ui/sidebar';\n\n\nlet nextId = 0;\n\n@Component({\n selector: 'ui-sidebar-group',\n templateUrl: './sidebar-group.component.html',\n styleUrl: './sidebar-group.component.css'\n})\nexport class UiSidebarGroupComponent {\n private readonly sidebar = inject(UiSidebarComponent, { optional: true });\n\n readonly label = input.required<string>();\n\n protected readonly labelId = `ui-sidebar-group-${nextId++}`;\n\n readonly isCollapsed = computed(() => this.sidebar?.isCollapsed() ?? false);\n}\n","@if (isCollapsed()) {\n <div class=\"ui-sidebar-group-divider\" aria-hidden=\"true\"></div>\n} @else {\n <span class=\"ui-sidebar-group-label ui-text-caption\" [id]=\"labelId\">{{ label() }}</span>\n}\n\n<div\n class=\"ui-sidebar-group-items\"\n role=\"group\"\n [attr.aria-labelledby]=\"isCollapsed() ? null : labelId\"\n [attr.aria-label]=\"isCollapsed() ? label() : null\"\n>\n <ng-content />\n</div>\n"],"mappings":";;;AAKA,IAAI,SAAS;AAOb,IAAa,0BAAb,MAAa,wBAAuB;CACf,UAAU,OAAO,oBAAoB,EAAE,UAAU,KAAI,CAAE;CAE/D,QAAQ,MAAM,SAAkB,GAAA,YAAA,CAAA,EAAA,WAAA,QAAA,CAAA,+BAAA,CAAA,CAAA;CAEtB,UAAU,oBAAoB;CAExC,cAAc,eAAe,KAAK,SAAS,YAAW,KAAM,OAAM,GAAA,YAAA,CAAA,EAAA,WAAA,cAAA,CAAA,+BAAA,CAAA,CAAA;CAPlE,OAAA,OAAA,GAAA,mBAAA;EAAA,YAAA;EAAA,SAAA;EAAA,UAAA;EAAA,MAAA;EAAuB,MAAA,CAAA;EAAA,QAAA,GAAA,gBAAA;CAAA,CAAA;CAAvB,OAAA,OAAA,GAAA,qBAAA;EAAA,YAAA;EAAA,SAAA;EAAA,MAAA;EAAuB,cAAA;EAAA,UAAA;EAAA,QAAA,EAAA,OAAA;GAAA,mBAAA;GAAA,YAAA;GAAA,UAAA;GAAA,YAAA;GAAA,mBAAA;EAAA,EAAA;EAAA,UAAA;EAAA,UCZpC;EAcA,QAAA,CAAA,66CAAA;CAAA,CAAA;;ADFa,GAAA,yBAAA;CAAA,YAAA;CAAA,SAAA;CAAA,UAAA;CAAA,MAAA;CAAuB,YAAA,CAAA;EALnC,MAAA;EACa,MAAA,CAAA;GAAA,UAAA;GAAkB,UAAA;GAAA,QAAA,CAAA,66CAAA;EAAA,CAAA"}
@@ -0,0 +1,107 @@
1
+ import * as i0 from "@angular/core";
2
+ import { Component, computed, inject, input } from "@angular/core";
3
+ import { UiButtonComponent } from "@area8975/ui/button";
4
+ import { UiSidebarComponent } from "@area8975/ui/sidebar";
5
+ import { NgIcon } from "@ng-icons/core";
6
+ var UiSidebarItemComponent = class UiSidebarItemComponent {
7
+ sidebar = inject(UiSidebarComponent, { optional: true });
8
+ label = input.required(...ngDevMode ? [{ debugName: "label" }] : /* istanbul ignore next */ []);
9
+ icon = input("", ...ngDevMode ? [{ debugName: "icon" }] : /* istanbul ignore next */ []);
10
+ isCollapsed = computed(() => this.sidebar ? !this.sidebar.isOpen() : false, ...ngDevMode ? [{ debugName: "isCollapsed" }] : /* istanbul ignore next */ []);
11
+ static ɵfac = i0.ɵɵngDeclareFactory({
12
+ minVersion: "12.0.0",
13
+ version: "22.2.1",
14
+ ngImport: i0,
15
+ type: UiSidebarItemComponent,
16
+ deps: [],
17
+ target: i0.ɵɵFactoryTarget.Component
18
+ });
19
+ static ɵcmp = i0.ɵɵngDeclareComponent({
20
+ minVersion: "17.0.0",
21
+ version: "22.2.1",
22
+ type: UiSidebarItemComponent,
23
+ isStandalone: true,
24
+ selector: "ui-sidebar-item",
25
+ inputs: {
26
+ label: {
27
+ classPropertyName: "label",
28
+ publicName: "label",
29
+ isSignal: true,
30
+ isRequired: true,
31
+ transformFunction: null
32
+ },
33
+ icon: {
34
+ classPropertyName: "icon",
35
+ publicName: "icon",
36
+ isSignal: true,
37
+ isRequired: false,
38
+ transformFunction: null
39
+ }
40
+ },
41
+ ngImport: i0,
42
+ template: "@if (!isCollapsed() || icon()) {\n <ui-button\n appearance=\"ghost\"\n intent=\"secondary\"\n class=\"block\"\n [classes]=\"isCollapsed()\n ? 'ui-sidebar-button ui-sidebar-item ui-sidebar-item--collapsed'\n : 'ui-sidebar-button ui-sidebar-item'\"\n [ariaLabel]=\"isCollapsed() ? label() : ''\"\n >\n @if (icon()) {\n <ng-icon [name]=\"icon()\" size=\"20\" class=\"shrink-0\" />\n }\n\n @if (!isCollapsed()) {\n <span class=\"truncate\">{{ label() }}</span>\n\n <span class=\"empty:hidden ms-auto\">\n <ng-content select=\"ui-badge\" />\n </span>\n }\n </ui-button>\n}\n",
43
+ styles: [":host{display:block}::ng-deep .ui-sidebar-item{height:calc(var(--spacing, .25rem) * 10);width:100%;padding-inline:calc(var(--spacing, .25rem) * 2.5)!important;padding-block:0px!important;white-space:nowrap}::ng-deep .ui-sidebar-item--collapsed{justify-content:center}\n/*! tailwindcss v4.3.3 | MIT License | https://tailwindcss.com */\n"],
44
+ dependencies: [{
45
+ kind: "component",
46
+ type: UiButtonComponent,
47
+ selector: "ui-button",
48
+ inputs: [
49
+ "appearance",
50
+ "intent",
51
+ "size",
52
+ "classes",
53
+ "type",
54
+ "ariaLabel",
55
+ "disabled",
56
+ "loading"
57
+ ]
58
+ }, {
59
+ kind: "component",
60
+ type: NgIcon,
61
+ selector: "ng-icon",
62
+ inputs: [
63
+ "name",
64
+ "svg",
65
+ "size",
66
+ "strokeWidth",
67
+ "color"
68
+ ]
69
+ }]
70
+ });
71
+ };
72
+ i0.ɵɵngDeclareClassMetadata({
73
+ minVersion: "12.0.0",
74
+ version: "22.2.1",
75
+ ngImport: i0,
76
+ type: UiSidebarItemComponent,
77
+ decorators: [{
78
+ type: Component,
79
+ args: [{
80
+ selector: "ui-sidebar-item",
81
+ imports: [UiButtonComponent, NgIcon],
82
+ template: "@if (!isCollapsed() || icon()) {\n <ui-button\n appearance=\"ghost\"\n intent=\"secondary\"\n class=\"block\"\n [classes]=\"isCollapsed()\n ? 'ui-sidebar-button ui-sidebar-item ui-sidebar-item--collapsed'\n : 'ui-sidebar-button ui-sidebar-item'\"\n [ariaLabel]=\"isCollapsed() ? label() : ''\"\n >\n @if (icon()) {\n <ng-icon [name]=\"icon()\" size=\"20\" class=\"shrink-0\" />\n }\n\n @if (!isCollapsed()) {\n <span class=\"truncate\">{{ label() }}</span>\n\n <span class=\"empty:hidden ms-auto\">\n <ng-content select=\"ui-badge\" />\n </span>\n }\n </ui-button>\n}\n",
83
+ styles: [":host{display:block}::ng-deep .ui-sidebar-item{height:calc(var(--spacing, .25rem) * 10);width:100%;padding-inline:calc(var(--spacing, .25rem) * 2.5)!important;padding-block:0px!important;white-space:nowrap}::ng-deep .ui-sidebar-item--collapsed{justify-content:center}\n/*! tailwindcss v4.3.3 | MIT License | https://tailwindcss.com */\n"]
84
+ }]
85
+ }],
86
+ propDecorators: {
87
+ label: [{
88
+ type: i0.Input,
89
+ args: [{
90
+ isSignal: true,
91
+ alias: "label",
92
+ required: true
93
+ }]
94
+ }],
95
+ icon: [{
96
+ type: i0.Input,
97
+ args: [{
98
+ isSignal: true,
99
+ alias: "icon",
100
+ required: false
101
+ }]
102
+ }]
103
+ }
104
+ });
105
+ export { UiSidebarItemComponent };
106
+
107
+ //# sourceMappingURL=area8975-ui-sidebar-item.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"area8975-ui-sidebar-item.mjs","names":[],"sources":["../../../projects/ui/sidebar-item/sidebar-item.component.ts","../../../projects/ui/sidebar-item/sidebar-item.component.html"],"sourcesContent":["import { Component, computed, inject, input } from '@angular/core';\n\nimport { UiButtonComponent } from '@area8975/ui/button';\nimport { UiSidebarComponent } from '@area8975/ui/sidebar';\nimport { NgIcon } from '@ng-icons/core';\n\n\n@Component({\n selector: 'ui-sidebar-item',\n templateUrl: './sidebar-item.component.html',\n styleUrl: './sidebar-item.component.css',\n imports: [UiButtonComponent, NgIcon]\n})\nexport class UiSidebarItemComponent {\n private readonly sidebar = inject(UiSidebarComponent, { optional: true });\n\n readonly label = input.required<string>();\n readonly icon = input<string>('');\n\n readonly isCollapsed = computed(() => this.sidebar ? !this.sidebar.isOpen() : false);\n}\n","@if (!isCollapsed() || icon()) {\n <ui-button\n appearance=\"ghost\"\n intent=\"secondary\"\n class=\"block\"\n [classes]=\"isCollapsed()\n ? 'ui-sidebar-button ui-sidebar-item ui-sidebar-item--collapsed'\n : 'ui-sidebar-button ui-sidebar-item'\"\n [ariaLabel]=\"isCollapsed() ? label() : ''\"\n >\n @if (icon()) {\n <ng-icon [name]=\"icon()\" size=\"20\" class=\"shrink-0\" />\n }\n\n @if (!isCollapsed()) {\n <span class=\"truncate\">{{ label() }}</span>\n\n <span class=\"empty:hidden ms-auto\">\n <ng-content select=\"ui-badge\" />\n </span>\n }\n </ui-button>\n}\n"],"mappings":";;;;;AAaA,IAAa,yBAAb,MAAa,uBAAsB;CACd,UAAU,OAAO,oBAAoB,EAAE,UAAU,KAAI,CAAE;CAE/D,QAAQ,MAAM,SAAkB,GAAA,YAAA,CAAA,EAAA,WAAA,QAAA,CAAA,+BAAA,CAAA,CAAA;CAChC,OAAO,MAAc,IAAG,GAAA,YAAA,CAAA,EAAA,WAAA,OAAA,CAAA,+BAAA,CAAA,CAAA;CAExB,cAAc,eAAe,KAAK,UAAU,CAAC,KAAK,QAAQ,OAAM,IAAK,OAAM,GAAA,YAAA,CAAA,EAAA,WAAA,cAAA,CAAA,+BAAA,CAAA,CAAA;CAN3E,OAAA,OAAA,GAAA,mBAAA;EAAA,YAAA;EAAA,SAAA;EAAA,UAAA;EAAA,MAAA;EAAsB,MAAA,CAAA;EAAA,QAAA,GAAA,gBAAA;CAAA,CAAA;CAAtB,OAAA,OAAA,GAAA,qBAAA;EAAA,YAAA;EAAA,SAAA;EAAA,MAAA;EAAsB,cAAA;EAAA,UAAA;EAAA,QAAA;GAAA,OAAA;IAAA,mBAAA;IAAA,YAAA;IAAA,UAAA;IAAA,YAAA;IAAA,mBAAA;GAAA;GAAA,MAAA;IAAA,mBAAA;IAAA,YAAA;IAAA,UAAA;IAAA,YAAA;IAAA,mBAAA;GAAA;EAAA;EAAA,UAAA;EAAA,UCbnC;EAuBA,QAAA,CAAA,kVAAA;EAAA,cAAA,CAAA;GAAA,MAAA;GAAA,MDZc;GAAiB,UAAA;GAAA,QAAA;IAAA;IAAA;IAAA;IAAA;IAAA;IAAA;IAAA;IAAA;GAAA;EAAA,GAAA;GAAA,MAAA;GAAA,MAAE;GAAM,UAAA;GAAA,QAAA;IAAA;IAAA;IAAA;IAAA;IAAA;GAAA;EAAA,CAAA;CAAA,CAAA;;AAE1B,GAAA,yBAAA;CAAA,YAAA;CAAA,SAAA;CAAA,UAAA;CAAA,MAAA;CAAsB,YAAA,CAAA;EANlC,MAAA;EACa,MAAA,CAAA;GAAA,UAAA;GAAiB,SAGlB,CAAC,mBAAmB,MAAM;GAAC,UAAA;GAAA,QAAA,CAAA,kVAAA;EAAA,CAAA"}
@@ -0,0 +1,109 @@
1
+ import * as i0 from "@angular/core";
2
+ import { Component, computed, model } from "@angular/core";
3
+ import { UiButtonComponent } from "@area8975/ui/button";
4
+ import { NgIcon, provideIcons } from "@ng-icons/core";
5
+ import { heroBars3, heroChevronDoubleLeft } from "@ng-icons/heroicons/outline";
6
+ var UiSidebarComponent = class UiSidebarComponent {
7
+ isOpen = model(false, ...ngDevMode ? [{ debugName: "isOpen" }] : /* istanbul ignore next */ []);
8
+ isCollapsed = computed(() => !this.isOpen(), ...ngDevMode ? [{ debugName: "isCollapsed" }] : /* istanbul ignore next */ []);
9
+ toggle = () => this.isOpen.update((isOpen) => !isOpen);
10
+ static ɵfac = i0.ɵɵngDeclareFactory({
11
+ minVersion: "12.0.0",
12
+ version: "22.2.1",
13
+ ngImport: i0,
14
+ type: UiSidebarComponent,
15
+ deps: [],
16
+ target: i0.ɵɵFactoryTarget.Component
17
+ });
18
+ static ɵcmp = i0.ɵɵngDeclareComponent({
19
+ minVersion: "17.0.0",
20
+ version: "22.2.1",
21
+ type: UiSidebarComponent,
22
+ isStandalone: true,
23
+ selector: "ui-sidebar",
24
+ inputs: { isOpen: {
25
+ classPropertyName: "isOpen",
26
+ publicName: "isOpen",
27
+ isSignal: true,
28
+ isRequired: false,
29
+ transformFunction: null
30
+ } },
31
+ outputs: { isOpen: "isOpenChange" },
32
+ host: {
33
+ listeners: { "document:keydown.escape": "isOpen.set(false)" },
34
+ properties: { "class.open": "isOpen()" }
35
+ },
36
+ providers: [provideIcons({
37
+ heroChevronDoubleLeft,
38
+ heroBars3
39
+ })],
40
+ exportAs: ["uiSidebar"],
41
+ ngImport: i0,
42
+ template: "<div class=\"ui-sidebar-backdrop\" aria-hidden=\"true\" (click)=\"isOpen.set(false)\">\n</div>\n\n<aside class=\"ui-sidebar-panel\">\n <div class=\"ui-sidebar-content\">\n <ng-content />\n </div>\n\n <footer class=\"ui-sidebar-footer\">\n <div class=\"ui-sidebar-footer-content\">\n <ng-content select=\"[sidebar-footer]\" />\n </div>\n\n <ui-button\n appearance=\"ghost\"\n intent=\"secondary\"\n size=\"sm\"\n classes=\"ui-sidebar-button justify-center size-10 p-0!\"\n [ariaLabel]=\"isOpen() ? 'Collapse sidebar' : 'Expand sidebar'\"\n (click)=\"toggle()\"\n >\n <ng-icon\n name=\"heroChevronDoubleLeft\"\n size=\"16\"\n strokeWidth=\"2\"\n class=\"duration-300 shrink-0\"\n [class.rotate-180]=\"!isOpen()\"\n />\n </ui-button>\n </footer>\n</aside>\n\n@if (!isOpen()) {\n <ui-button\n appearance=\"white\"\n intent=\"secondary\"\n class=\"ui-sidebar-open-btn\"\n classes=\"p-3! rounded-full! shadow-lg!\"\n ariaLabel=\"Open sidebar\"\n (click)=\"isOpen.set(true)\"\n >\n <ng-icon name=\"heroBars3\" size=\"20\" strokeWidth=\"2\" class=\"shrink-0\" />\n </ui-button>\n}\n",
43
+ styles: ["@layer properties;:host{pointer-events:none;position:fixed;inset:0;z-index:50}@media(width>=48rem){:host{pointer-events:auto}}@media(width>=48rem){:host{position:static}}@media(width>=48rem){:host{display:block}}@media(width>=48rem){:host{height:100%}}.ui-sidebar-backdrop{position:absolute;inset:0;background-color:color-mix(in srgb,#000 10%,transparent);opacity:0%;transition-property:opacity;transition-timing-function:var(--tw-ease, var(--default-transition-timing-function, cubic-bezier(.4, 0, .2, 1)));transition-duration:var(--tw-duration, var(--default-transition-duration, .15s));--tw-duration: .2s;transition-duration:.2s}@supports (color: color-mix(in lab,red,red)){.ui-sidebar-backdrop{background-color:color-mix(in oklab,var(--color-black, #000) 10%,transparent)}}@media(width>=48rem){.ui-sidebar-backdrop{display:none}}:host(.open) .ui-sidebar-backdrop{pointer-events:auto;opacity:100%}.ui-sidebar-panel{pointer-events:auto;position:absolute;inset-block:0px;left:0;display:flex;height:100%;width:calc(var(--spacing, .25rem) * 60);--tw-translate-x: -100%;translate:var(--tw-translate-x) var(--tw-translate-y);flex-direction:column;border-right-style:var(--tw-border-style);border-right-width:1px;border-color:var(--sidebar-line);background-color:var(--sidebar);transition-property:translate,width,visibility;transition-timing-function:var(--tw-ease, var(--default-transition-timing-function, cubic-bezier(.4, 0, .2, 1)));transition-duration:var(--tw-duration, var(--default-transition-duration, .15s));--tw-duration: .2s;transition-duration:.2s}@media(width<48rem){.ui-sidebar-panel{visibility:hidden}}@media(width>=48rem){.ui-sidebar-panel{position:relative}}@media(width>=48rem){.ui-sidebar-panel{width:calc(var(--spacing, .25rem) * 16)}}@media(width>=48rem){.ui-sidebar-panel{translate:none}}@media(width<48rem){:host(.open) .ui-sidebar-panel{visibility:visible;--tw-translate-x: 0px;translate:var(--tw-translate-x) var(--tw-translate-y)}}@media(width>=48rem){:host(.open) .ui-sidebar-panel{width:calc(var(--spacing, .25rem) * 60)}}.ui-sidebar-content{display:flex;min-height:0px;flex-grow:1;flex-direction:column;align-items:flex-start;row-gap:var(--spacing, .25rem);overflow-x:hidden;overflow-y:auto;padding:calc(var(--spacing, .25rem) * 3)}:host(.open) .ui-sidebar-content{align-items:stretch}.ui-sidebar-footer{display:flex;flex-shrink:0;flex-direction:column;align-items:center;gap:calc(var(--spacing, .25rem) * 2);padding:calc(var(--spacing, .25rem) * 3)}:host(.open) .ui-sidebar-footer{flex-direction:row;justify-content:flex-end}.ui-sidebar-footer-content{display:flex;min-width:0px;justify-content:center}.ui-sidebar-footer-content:empty{display:none}:host(.open) .ui-sidebar-footer-content{flex-grow:1;justify-content:flex-start}::ng-deep .ui-button.ui-sidebar-button{color:var(--sidebar-nav-foreground)}::ng-deep .ui-button.ui-sidebar-button:hover{background-color:var(--sidebar-nav-hover)}::ng-deep .ui-button.ui-sidebar-button:focus-visible{background-color:var(--sidebar-nav-focus)}.ui-sidebar-open-btn{pointer-events:auto;position:fixed;bottom:calc(var(--spacing, .25rem) * 4);left:calc(var(--spacing, .25rem) * 4)}@media(width>=48rem){.ui-sidebar-open-btn{display:none}}@property --tw-duration{syntax: \"*\"; inherits: false;}@property --tw-translate-x{syntax: \"*\"; inherits: false; initial-value: 0;}@property --tw-translate-y{syntax: \"*\"; inherits: false; initial-value: 0;}@property --tw-translate-z{syntax: \"*\"; inherits: false; initial-value: 0;}@property --tw-border-style{syntax: \"*\"; inherits: false; initial-value: solid;}@layer properties{@supports ((-webkit-hyphens: none) and (not (margin-trim: inline))) or ((-moz-orient: inline) and (not (color:rgb(from red r g b)))){*,:before,:after,::backdrop{--tw-duration: initial;--tw-translate-x: 0;--tw-translate-y: 0;--tw-translate-z: 0;--tw-border-style: solid}}}\n/*! tailwindcss v4.3.3 | MIT License | https://tailwindcss.com */\n"],
44
+ dependencies: [{
45
+ kind: "component",
46
+ type: UiButtonComponent,
47
+ selector: "ui-button",
48
+ inputs: [
49
+ "appearance",
50
+ "intent",
51
+ "size",
52
+ "classes",
53
+ "type",
54
+ "ariaLabel",
55
+ "disabled",
56
+ "loading"
57
+ ]
58
+ }, {
59
+ kind: "component",
60
+ type: NgIcon,
61
+ selector: "ng-icon",
62
+ inputs: [
63
+ "name",
64
+ "svg",
65
+ "size",
66
+ "strokeWidth",
67
+ "color"
68
+ ]
69
+ }]
70
+ });
71
+ };
72
+ i0.ɵɵngDeclareClassMetadata({
73
+ minVersion: "12.0.0",
74
+ version: "22.2.1",
75
+ ngImport: i0,
76
+ type: UiSidebarComponent,
77
+ decorators: [{
78
+ type: Component,
79
+ args: [{
80
+ selector: "ui-sidebar",
81
+ exportAs: "uiSidebar",
82
+ imports: [UiButtonComponent, NgIcon],
83
+ host: {
84
+ "[class.open]": "isOpen()",
85
+ "(document:keydown.escape)": "isOpen.set(false)"
86
+ },
87
+ providers: [provideIcons({
88
+ heroChevronDoubleLeft,
89
+ heroBars3
90
+ })],
91
+ template: "<div class=\"ui-sidebar-backdrop\" aria-hidden=\"true\" (click)=\"isOpen.set(false)\">\n</div>\n\n<aside class=\"ui-sidebar-panel\">\n <div class=\"ui-sidebar-content\">\n <ng-content />\n </div>\n\n <footer class=\"ui-sidebar-footer\">\n <div class=\"ui-sidebar-footer-content\">\n <ng-content select=\"[sidebar-footer]\" />\n </div>\n\n <ui-button\n appearance=\"ghost\"\n intent=\"secondary\"\n size=\"sm\"\n classes=\"ui-sidebar-button justify-center size-10 p-0!\"\n [ariaLabel]=\"isOpen() ? 'Collapse sidebar' : 'Expand sidebar'\"\n (click)=\"toggle()\"\n >\n <ng-icon\n name=\"heroChevronDoubleLeft\"\n size=\"16\"\n strokeWidth=\"2\"\n class=\"duration-300 shrink-0\"\n [class.rotate-180]=\"!isOpen()\"\n />\n </ui-button>\n </footer>\n</aside>\n\n@if (!isOpen()) {\n <ui-button\n appearance=\"white\"\n intent=\"secondary\"\n class=\"ui-sidebar-open-btn\"\n classes=\"p-3! rounded-full! shadow-lg!\"\n ariaLabel=\"Open sidebar\"\n (click)=\"isOpen.set(true)\"\n >\n <ng-icon name=\"heroBars3\" size=\"20\" strokeWidth=\"2\" class=\"shrink-0\" />\n </ui-button>\n}\n",
92
+ styles: ["@layer properties;:host{pointer-events:none;position:fixed;inset:0;z-index:50}@media(width>=48rem){:host{pointer-events:auto}}@media(width>=48rem){:host{position:static}}@media(width>=48rem){:host{display:block}}@media(width>=48rem){:host{height:100%}}.ui-sidebar-backdrop{position:absolute;inset:0;background-color:color-mix(in srgb,#000 10%,transparent);opacity:0%;transition-property:opacity;transition-timing-function:var(--tw-ease, var(--default-transition-timing-function, cubic-bezier(.4, 0, .2, 1)));transition-duration:var(--tw-duration, var(--default-transition-duration, .15s));--tw-duration: .2s;transition-duration:.2s}@supports (color: color-mix(in lab,red,red)){.ui-sidebar-backdrop{background-color:color-mix(in oklab,var(--color-black, #000) 10%,transparent)}}@media(width>=48rem){.ui-sidebar-backdrop{display:none}}:host(.open) .ui-sidebar-backdrop{pointer-events:auto;opacity:100%}.ui-sidebar-panel{pointer-events:auto;position:absolute;inset-block:0px;left:0;display:flex;height:100%;width:calc(var(--spacing, .25rem) * 60);--tw-translate-x: -100%;translate:var(--tw-translate-x) var(--tw-translate-y);flex-direction:column;border-right-style:var(--tw-border-style);border-right-width:1px;border-color:var(--sidebar-line);background-color:var(--sidebar);transition-property:translate,width,visibility;transition-timing-function:var(--tw-ease, var(--default-transition-timing-function, cubic-bezier(.4, 0, .2, 1)));transition-duration:var(--tw-duration, var(--default-transition-duration, .15s));--tw-duration: .2s;transition-duration:.2s}@media(width<48rem){.ui-sidebar-panel{visibility:hidden}}@media(width>=48rem){.ui-sidebar-panel{position:relative}}@media(width>=48rem){.ui-sidebar-panel{width:calc(var(--spacing, .25rem) * 16)}}@media(width>=48rem){.ui-sidebar-panel{translate:none}}@media(width<48rem){:host(.open) .ui-sidebar-panel{visibility:visible;--tw-translate-x: 0px;translate:var(--tw-translate-x) var(--tw-translate-y)}}@media(width>=48rem){:host(.open) .ui-sidebar-panel{width:calc(var(--spacing, .25rem) * 60)}}.ui-sidebar-content{display:flex;min-height:0px;flex-grow:1;flex-direction:column;align-items:flex-start;row-gap:var(--spacing, .25rem);overflow-x:hidden;overflow-y:auto;padding:calc(var(--spacing, .25rem) * 3)}:host(.open) .ui-sidebar-content{align-items:stretch}.ui-sidebar-footer{display:flex;flex-shrink:0;flex-direction:column;align-items:center;gap:calc(var(--spacing, .25rem) * 2);padding:calc(var(--spacing, .25rem) * 3)}:host(.open) .ui-sidebar-footer{flex-direction:row;justify-content:flex-end}.ui-sidebar-footer-content{display:flex;min-width:0px;justify-content:center}.ui-sidebar-footer-content:empty{display:none}:host(.open) .ui-sidebar-footer-content{flex-grow:1;justify-content:flex-start}::ng-deep .ui-button.ui-sidebar-button{color:var(--sidebar-nav-foreground)}::ng-deep .ui-button.ui-sidebar-button:hover{background-color:var(--sidebar-nav-hover)}::ng-deep .ui-button.ui-sidebar-button:focus-visible{background-color:var(--sidebar-nav-focus)}.ui-sidebar-open-btn{pointer-events:auto;position:fixed;bottom:calc(var(--spacing, .25rem) * 4);left:calc(var(--spacing, .25rem) * 4)}@media(width>=48rem){.ui-sidebar-open-btn{display:none}}@property --tw-duration{syntax: \"*\"; inherits: false;}@property --tw-translate-x{syntax: \"*\"; inherits: false; initial-value: 0;}@property --tw-translate-y{syntax: \"*\"; inherits: false; initial-value: 0;}@property --tw-translate-z{syntax: \"*\"; inherits: false; initial-value: 0;}@property --tw-border-style{syntax: \"*\"; inherits: false; initial-value: solid;}@layer properties{@supports ((-webkit-hyphens: none) and (not (margin-trim: inline))) or ((-moz-orient: inline) and (not (color:rgb(from red r g b)))){*,:before,:after,::backdrop{--tw-duration: initial;--tw-translate-x: 0;--tw-translate-y: 0;--tw-translate-z: 0;--tw-border-style: solid}}}\n/*! tailwindcss v4.3.3 | MIT License | https://tailwindcss.com */\n"]
93
+ }]
94
+ }],
95
+ propDecorators: { isOpen: [{
96
+ type: i0.Input,
97
+ args: [{
98
+ isSignal: true,
99
+ alias: "isOpen",
100
+ required: false
101
+ }]
102
+ }, {
103
+ type: i0.Output,
104
+ args: ["isOpenChange"]
105
+ }] }
106
+ });
107
+ export { UiSidebarComponent };
108
+
109
+ //# sourceMappingURL=area8975-ui-sidebar.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"area8975-ui-sidebar.mjs","names":[],"sources":["../../../projects/ui/sidebar/sidebar.component.ts","../../../projects/ui/sidebar/sidebar.component.html"],"sourcesContent":["import { Component, computed, model } from '@angular/core';\n\nimport { UiButtonComponent } from '@area8975/ui/button';\nimport { NgIcon, provideIcons } from '@ng-icons/core';\nimport { heroBars3, heroChevronDoubleLeft } from '@ng-icons/heroicons/outline';\n\n\n@Component({\n selector: 'ui-sidebar',\n exportAs: 'uiSidebar',\n templateUrl: './sidebar.component.html',\n styleUrl: './sidebar.component.css',\n imports: [UiButtonComponent, NgIcon],\n host: {\n '[class.open]': 'isOpen()',\n '(document:keydown.escape)': 'isOpen.set(false)'\n },\n providers: [provideIcons({ heroChevronDoubleLeft, heroBars3 })]\n})\nexport class UiSidebarComponent {\n readonly isOpen = model<boolean>(false);\n\n readonly isCollapsed = computed(() => !this.isOpen());\n\n readonly toggle = () => this.isOpen.update(isOpen => !isOpen);\n}\n","<div class=\"ui-sidebar-backdrop\" aria-hidden=\"true\" (click)=\"isOpen.set(false)\">\n</div>\n\n<aside class=\"ui-sidebar-panel\">\n <div class=\"ui-sidebar-content\">\n <ng-content />\n </div>\n\n <footer class=\"ui-sidebar-footer\">\n <div class=\"ui-sidebar-footer-content\">\n <ng-content select=\"[sidebar-footer]\" />\n </div>\n\n <ui-button\n appearance=\"ghost\"\n intent=\"secondary\"\n size=\"sm\"\n classes=\"ui-sidebar-button justify-center size-10 p-0!\"\n [ariaLabel]=\"isOpen() ? 'Collapse sidebar' : 'Expand sidebar'\"\n (click)=\"toggle()\"\n >\n <ng-icon\n name=\"heroChevronDoubleLeft\"\n size=\"16\"\n strokeWidth=\"2\"\n class=\"duration-300 shrink-0\"\n [class.rotate-180]=\"!isOpen()\"\n />\n </ui-button>\n </footer>\n</aside>\n\n@if (!isOpen()) {\n <ui-button\n appearance=\"white\"\n intent=\"secondary\"\n class=\"ui-sidebar-open-btn\"\n classes=\"p-3! rounded-full! shadow-lg!\"\n ariaLabel=\"Open sidebar\"\n (click)=\"isOpen.set(true)\"\n >\n <ng-icon name=\"heroBars3\" size=\"20\" strokeWidth=\"2\" class=\"shrink-0\" />\n </ui-button>\n}\n"],"mappings":";;;;;AAmBA,IAAa,qBAAb,MAAa,mBAAkB;CAClB,SAAS,MAAe,OAAM,GAAA,YAAA,CAAA,EAAA,WAAA,SAAA,CAAA,+BAAA,CAAA,CAAA;CAE9B,cAAc,eAAe,CAAC,KAAK,OAAM,GAAG,GAAA,YAAA,CAAA,EAAA,WAAA,cAAA,CAAA,+BAAA,CAAA,CAAA;CAE5C,eAAe,KAAK,OAAO,QAAO,WAAU,CAAC,MAAM;CALnD,OAAA,OAAA,GAAA,mBAAA;EAAA,YAAA;EAAA,SAAA;EAAA,UAAA;EAAA,MAAA;EAAkB,MAAA,CAAA;EAAA,QAAA,GAAA,gBAAA;CAAA,CAAA;CAAlB,OAAA,OAAA,GAAA,qBAAA;EAAA,YAAA;EAAA,SAAA;EAAA,MAAA;EAAkB,cAAA;EAAA,UAAA;EAAA,QAAA,EAAA,QAAA;GAAA,mBAAA;GAAA,YAAA;GAAA,UAAA;GAAA,YAAA;GAAA,mBAAA;EAAA,EAAA;EAAA,SAAA,EAAA,QAAA,eAAA;EAAA,MAAA;GAAA,WAAA,EAAA,2BAAA,oBAAA;GAAA,YAAA,EAAA,cAAA,WAAA;EAAA;EAAA,WAFhB,CAAC,aAAa;GAAE;GAAuB;EAAS,CAAE,CAAC;EAAC,UAAA,CAAA,WAAA;EAAA,UAAA;EAAA,UCjBnE;EA4CA,QAAA,CAAA,21HAAA;EAAA,cAAA,CAAA;GAAA,MAAA;GAAA,MDhCc;GAAiB,UAAA;GAAA,QAAA;IAAA;IAAA;IAAA;IAAA;IAAA;IAAA;IAAA;IAAA;GAAA;EAAA,GAAA;GAAA,MAAA;GAAA,MAAE;GAAM,UAAA;GAAA,QAAA;IAAA;IAAA;IAAA;IAAA;IAAA;GAAA;EAAA,CAAA;CAAA,CAAA;;AAO1B,GAAA,yBAAA;CAAA,YAAA;CAAA,SAAA;CAAA,UAAA;CAAA,MAAA;CAAkB,YAAA,CAAA;EAZ9B,MAAA;EACa,MAAA,CAAA;GAAA,UAAA;GAAY,UACZ;GAAW,SAGZ,CAAC,mBAAmB,MAAM;GAAC,MAC9B;IACF,gBAAgB;IAChB,6BAA6B;GAChC;GAAA,WACU,CAAC,aAAa;IAAE;IAAuB;GAAS,CAAE,CAAC;GAAC,UAAA;GAAA,QAAA,CAAA,21HAAA;EAAA,CAAA"}
@@ -0,0 +1,116 @@
1
+ import * as i0 from "@angular/core";
2
+ import { Component, booleanAttribute, computed, input, numberAttribute } from "@angular/core";
3
+ var UiSkeletonComponent = class UiSkeletonComponent {
4
+ shape = input("text", ...ngDevMode ? [{ debugName: "shape" }] : /* istanbul ignore next */ []);
5
+ animated = input(true, {
6
+ ...ngDevMode ? { debugName: "animated" } : /* istanbul ignore next */ {},
7
+ transform: booleanAttribute
8
+ });
9
+ lines = input(1, {
10
+ ...ngDevMode ? { debugName: "lines" } : /* istanbul ignore next */ {},
11
+ transform: numberAttribute
12
+ });
13
+ lineIndexes = computed(() => Array.from({ length: Math.max(1, Math.floor(this.lines())) }, (_, index) => index), ...ngDevMode ? [{ debugName: "lineIndexes" }] : /* istanbul ignore next */ []);
14
+ generatedClasses = computed(() => [
15
+ "ui-skeleton",
16
+ `ui-skeleton--${this.shape()}`,
17
+ this.animated() ? "ui-skeleton--animated" : ""
18
+ ].filter(Boolean).join(" "), ...ngDevMode ? [{ debugName: "generatedClasses" }] : /* istanbul ignore next */ []);
19
+ static ɵfac = i0.ɵɵngDeclareFactory({
20
+ minVersion: "12.0.0",
21
+ version: "22.2.1",
22
+ ngImport: i0,
23
+ type: UiSkeletonComponent,
24
+ deps: [],
25
+ target: i0.ɵɵFactoryTarget.Component
26
+ });
27
+ static ɵcmp = i0.ɵɵngDeclareComponent({
28
+ minVersion: "17.0.0",
29
+ version: "22.2.1",
30
+ type: UiSkeletonComponent,
31
+ isStandalone: true,
32
+ selector: "ui-skeleton",
33
+ inputs: {
34
+ shape: {
35
+ classPropertyName: "shape",
36
+ publicName: "shape",
37
+ isSignal: true,
38
+ isRequired: false,
39
+ transformFunction: null
40
+ },
41
+ animated: {
42
+ classPropertyName: "animated",
43
+ publicName: "animated",
44
+ isSignal: true,
45
+ isRequired: false,
46
+ transformFunction: null
47
+ },
48
+ lines: {
49
+ classPropertyName: "lines",
50
+ publicName: "lines",
51
+ isSignal: true,
52
+ isRequired: false,
53
+ transformFunction: null
54
+ }
55
+ },
56
+ host: {
57
+ attributes: { "aria-hidden": "true" },
58
+ properties: { "class": "generatedClasses()" }
59
+ },
60
+ ngImport: i0,
61
+ template: "@if (shape() === 'text') {\n @for (index of lineIndexes(); track index) {\n <span class=\"ui-skeleton-line\"></span>\n }\n} @else {\n <span class=\"ui-skeleton-block\"></span>\n}\n",
62
+ styles: [":host{display:block}@media(prefers-reduced-motion:no-preference){:host(.ui-skeleton--animated){animation:ui-skeleton-pulse 2s cubic-bezier(.4,0,.6,1) infinite}}.ui-skeleton-line,.ui-skeleton-block{display:block;background-color:var(--surface-1)}:host(.ui-skeleton--text){display:flex;flex-direction:column;row-gap:calc(var(--spacing, .25rem) * 3)}.ui-skeleton-line{height:calc(var(--spacing, .25rem) * 4);width:100%;border-radius:var(--radius-full, calc(infinity * 1px))}.ui-skeleton-line:last-child:not(:first-child){width:calc(3 / 5 * 100%)}.ui-skeleton-block{width:100%;height:100%}:host(.ui-skeleton--circle) .ui-skeleton-block{border-radius:var(--radius-full, calc(infinity * 1px))}:host(.ui-skeleton--rect) .ui-skeleton-block{border-radius:var(--radius-lg, .5rem)}@keyframes ui-skeleton-pulse{50%{opacity:.5}}\n/*! tailwindcss v4.3.3 | MIT License | https://tailwindcss.com */\n"]
63
+ });
64
+ };
65
+ i0.ɵɵngDeclareClassMetadata({
66
+ minVersion: "12.0.0",
67
+ version: "22.2.1",
68
+ ngImport: i0,
69
+ type: UiSkeletonComponent,
70
+ decorators: [{
71
+ type: Component,
72
+ args: [{
73
+ selector: "ui-skeleton",
74
+ host: {
75
+ "aria-hidden": "true",
76
+ "[class]": "generatedClasses()"
77
+ },
78
+ template: "@if (shape() === 'text') {\n @for (index of lineIndexes(); track index) {\n <span class=\"ui-skeleton-line\"></span>\n }\n} @else {\n <span class=\"ui-skeleton-block\"></span>\n}\n",
79
+ styles: [":host{display:block}@media(prefers-reduced-motion:no-preference){:host(.ui-skeleton--animated){animation:ui-skeleton-pulse 2s cubic-bezier(.4,0,.6,1) infinite}}.ui-skeleton-line,.ui-skeleton-block{display:block;background-color:var(--surface-1)}:host(.ui-skeleton--text){display:flex;flex-direction:column;row-gap:calc(var(--spacing, .25rem) * 3)}.ui-skeleton-line{height:calc(var(--spacing, .25rem) * 4);width:100%;border-radius:var(--radius-full, calc(infinity * 1px))}.ui-skeleton-line:last-child:not(:first-child){width:calc(3 / 5 * 100%)}.ui-skeleton-block{width:100%;height:100%}:host(.ui-skeleton--circle) .ui-skeleton-block{border-radius:var(--radius-full, calc(infinity * 1px))}:host(.ui-skeleton--rect) .ui-skeleton-block{border-radius:var(--radius-lg, .5rem)}@keyframes ui-skeleton-pulse{50%{opacity:.5}}\n/*! tailwindcss v4.3.3 | MIT License | https://tailwindcss.com */\n"]
80
+ }]
81
+ }],
82
+ propDecorators: {
83
+ shape: [{
84
+ type: i0.Input,
85
+ args: [{
86
+ isSignal: true,
87
+ alias: "shape",
88
+ required: false
89
+ }]
90
+ }],
91
+ animated: [{
92
+ type: i0.Input,
93
+ args: [{
94
+ isSignal: true,
95
+ alias: "animated",
96
+ required: false
97
+ }]
98
+ }],
99
+ lines: [{
100
+ type: i0.Input,
101
+ args: [{
102
+ isSignal: true,
103
+ alias: "lines",
104
+ required: false
105
+ }]
106
+ }]
107
+ }
108
+ });
109
+ const SkeletonShapes = [
110
+ "text",
111
+ "circle",
112
+ "rect"
113
+ ];
114
+ export { SkeletonShapes, UiSkeletonComponent };
115
+
116
+ //# sourceMappingURL=area8975-ui-skeleton.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"area8975-ui-skeleton.mjs","names":[],"sources":["../../../projects/ui/skeleton/skeleton.component.ts","../../../projects/ui/skeleton/skeleton.component.html","../../../projects/ui/skeleton/skeleton.types.ts"],"sourcesContent":["import {\n booleanAttribute,\n Component,\n computed,\n input,\n numberAttribute\n} from '@angular/core';\n\nimport type { SkeletonShape } from './skeleton.types';\n\n\n/**\n * A placeholder shown while content loads. Size it with classes on the\n * element, e.g. `class=\"w-48\"` for text or `class=\"size-12\"` for a circle.\n */\n@Component({\n selector: 'ui-skeleton',\n templateUrl: './skeleton.component.html',\n styleUrl: './skeleton.component.css',\n host: {\n // purely visual, the loading region should set aria-busy instead\n 'aria-hidden': 'true',\n '[class]': 'generatedClasses()'\n }\n})\nexport class UiSkeletonComponent {\n readonly shape = input<SkeletonShape>('text');\n readonly animated = input(true, { transform: booleanAttribute });\n\n /** Text only, stacks this many lines with a shorter last one. */\n readonly lines = input(1, { transform: numberAttribute });\n\n protected readonly lineIndexes = computed(() =>\n Array.from(\n { length: Math.max(1, Math.floor(this.lines())) },\n (_, index) => index\n )\n );\n\n readonly generatedClasses = computed(() =>\n [\n 'ui-skeleton',\n `ui-skeleton--${this.shape()}`,\n this.animated() ? 'ui-skeleton--animated' : ''\n ]\n .filter(Boolean)\n .join(' ')\n );\n}\n","@if (shape() === 'text') {\n @for (index of lineIndexes(); track index) {\n <span class=\"ui-skeleton-line\"></span>\n }\n} @else {\n <span class=\"ui-skeleton-block\"></span>\n}\n","/** What a skeleton stands in for, lines of text, an avatar or a block. */\nexport const SkeletonShapes = ['text', 'circle', 'rect'] as const;\n\n/** @see {@link SkeletonShapes} */\nexport type SkeletonShape = typeof SkeletonShapes[number];\n"],"mappings":";;AAyBA,IAAa,sBAAb,MAAa,oBAAmB;CACnB,QAAQ,MAAqB,QAAO,GAAA,YAAA,CAAA,EAAA,WAAA,QAAA,CAAA,+BAAA,CAAA,CAAA;CACpC,WAAW,MAAM,MAAI;EAAA,GAAA,YAAA,EAAA,WAAA,WAAA,+BAAA,CAAA;EAAI,WAAW;CAAgB,CAAA;CAGpD,QAAQ,MAAM,GAAC;EAAA,GAAA,YAAA,EAAA,WAAA,QAAA,+BAAA,CAAA;EAAI,WAAW;CAAe,CAAA;CAEnC,cAAc,eAC7B,MAAM,KACF,EAAE,QAAQ,KAAK,IAAI,GAAG,KAAK,MAAM,KAAK,MAAK,CAAE,CAAC,EAAC,IAC9C,GAAG,UAAU,KAAK,GAE1B,GAAA,YAAA,CAAA,EAAA,WAAA,cAAA,CAAA,+BAAA,CAAA,CAAA;CAEQ,mBAAmB,eACxB;EACI;EACA,gBAAgB,KAAK,MAAK;EAC1B,KAAK,SAAQ,IAAK,0BAA0B;CAC/C,CAAA,CACI,OAAO,OAAO,CAAC,CACf,KAAK,GAAG,GAChB,GAAA,YAAA,CAAA,EAAA,WAAA,mBAAA,CAAA,+BAAA,CAAA,CAAA;CAtBQ,OAAA,OAAA,GAAA,mBAAA;EAAA,YAAA;EAAA,SAAA;EAAA,UAAA;EAAA,MAAA;EAAmB,MAAA,CAAA;EAAA,QAAA,GAAA,gBAAA;CAAA,CAAA;CAAnB,OAAA,OAAA,GAAA,qBAAA;EAAA,YAAA;EAAA,SAAA;EAAA,MAAA;EAAmB,cAAA;EAAA,UAAA;EAAA,QAAA;GAAA,OAAA;IAAA,mBAAA;IAAA,YAAA;IAAA,UAAA;IAAA,YAAA;IAAA,mBAAA;GAAA;GAAA,UAAA;IAAA,mBAAA;IAAA,YAAA;IAAA,UAAA;IAAA,YAAA;IAAA,mBAAA;GAAA;GAAA,OAAA;IAAA,mBAAA;IAAA,YAAA;IAAA,UAAA;IAAA,YAAA;IAAA,mBAAA;GAAA;EAAA;EAAA,MAAA;GAAA,YAAA,EAAA,eAAA,OAAA;GAAA,YAAA,EAAA,SAAA,qBAAA;EAAA;EAAA,UAAA;EAAA,UCzBhC;EAOA,QAAA,CAAA,s3BAAA;CAAA,CAAA;;ADkBa,GAAA,yBAAA;CAAA,YAAA;CAAA,SAAA;CAAA,UAAA;CAAA,MAAA;CAAmB,YAAA,CAAA;EAV/B,MAAA;EACa,MAAA,CAAA;GAAA,UAAA;GAAa,MAGjB;IAEF,eAAe;IACf,WAAW;GACd;GAAA,UAAA;GAAA,QAAA,CAAA,s3BAAA;EAAA,CAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AEtBL,MAAa,iBAAiB;CAAC;CAAQ;CAAU;AAAM"}