@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.
- package/README.md +3 -2
- package/fesm2022/area8975-ui-alert.mjs +113 -0
- package/fesm2022/area8975-ui-alert.mjs.map +1 -0
- package/fesm2022/area8975-ui-avatar.mjs +157 -0
- package/fesm2022/area8975-ui-avatar.mjs.map +1 -0
- package/fesm2022/area8975-ui-badge.mjs +116 -0
- package/fesm2022/area8975-ui-badge.mjs.map +1 -0
- package/fesm2022/area8975-ui-button.mjs +314 -0
- package/fesm2022/area8975-ui-button.mjs.map +1 -0
- package/fesm2022/area8975-ui-calendar.mjs +549 -0
- package/fesm2022/area8975-ui-calendar.mjs.map +1 -0
- package/fesm2022/area8975-ui-card-header.mjs +96 -0
- package/fesm2022/area8975-ui-card-header.mjs.map +1 -0
- package/fesm2022/area8975-ui-card.mjs +73 -0
- package/fesm2022/area8975-ui-card.mjs.map +1 -0
- package/fesm2022/area8975-ui-chart-palette.mjs +225 -0
- package/fesm2022/area8975-ui-chart-palette.mjs.map +1 -0
- package/fesm2022/area8975-ui-charts.mjs +2813 -0
- package/fesm2022/area8975-ui-charts.mjs.map +1 -0
- package/fesm2022/area8975-ui-checkbox.mjs +202 -0
- package/fesm2022/area8975-ui-checkbox.mjs.map +1 -0
- package/fesm2022/area8975-ui-colour.mjs +200 -0
- package/fesm2022/area8975-ui-colour.mjs.map +1 -0
- package/fesm2022/area8975-ui-container.mjs +40 -0
- package/fesm2022/area8975-ui-container.mjs.map +1 -0
- package/fesm2022/area8975-ui-counter.mjs +246 -0
- package/fesm2022/area8975-ui-counter.mjs.map +1 -0
- package/fesm2022/area8975-ui-date-range-picker.mjs +554 -0
- package/fesm2022/area8975-ui-date-range-picker.mjs.map +1 -0
- package/fesm2022/area8975-ui-datepicker.mjs +547 -0
- package/fesm2022/area8975-ui-datepicker.mjs.map +1 -0
- package/fesm2022/area8975-ui-disclosure.mjs +279 -0
- package/fesm2022/area8975-ui-disclosure.mjs.map +1 -0
- package/fesm2022/area8975-ui-drawer.mjs +106 -0
- package/fesm2022/area8975-ui-drawer.mjs.map +1 -0
- package/fesm2022/area8975-ui-dropdown-button.mjs +141 -0
- package/fesm2022/area8975-ui-dropdown-button.mjs.map +1 -0
- package/fesm2022/area8975-ui-dropdown-menu.mjs +96 -0
- package/fesm2022/area8975-ui-dropdown-menu.mjs.map +1 -0
- package/fesm2022/area8975-ui-dropdown.mjs +208 -0
- package/fesm2022/area8975-ui-dropdown.mjs.map +1 -0
- package/fesm2022/area8975-ui-dropzone.mjs +332 -0
- package/fesm2022/area8975-ui-dropzone.mjs.map +1 -0
- package/fesm2022/area8975-ui-field.mjs +191 -0
- package/fesm2022/area8975-ui-field.mjs.map +1 -0
- package/fesm2022/area8975-ui-file-input.mjs +340 -0
- package/fesm2022/area8975-ui-file-input.mjs.map +1 -0
- package/fesm2022/area8975-ui-file.mjs +47 -0
- package/fesm2022/area8975-ui-file.mjs.map +1 -0
- package/fesm2022/area8975-ui-format.mjs +70 -0
- package/fesm2022/area8975-ui-format.mjs.map +1 -0
- package/fesm2022/area8975-ui-input-addon.mjs +42 -0
- package/fesm2022/area8975-ui-input-addon.mjs.map +1 -0
- package/fesm2022/area8975-ui-input-group.mjs +86 -0
- package/fesm2022/area8975-ui-input-group.mjs.map +1 -0
- package/fesm2022/area8975-ui-input.mjs +682 -0
- package/fesm2022/area8975-ui-input.mjs.map +1 -0
- package/fesm2022/area8975-ui-kpi.mjs +167 -0
- package/fesm2022/area8975-ui-kpi.mjs.map +1 -0
- package/fesm2022/area8975-ui-layout.mjs +63 -0
- package/fesm2022/area8975-ui-layout.mjs.map +1 -0
- package/fesm2022/area8975-ui-loading.mjs +76 -0
- package/fesm2022/area8975-ui-loading.mjs.map +1 -0
- package/fesm2022/area8975-ui-modal-close-btn.mjs +89 -0
- package/fesm2022/area8975-ui-modal-close-btn.mjs.map +1 -0
- package/fesm2022/area8975-ui-modal.mjs +235 -0
- package/fesm2022/area8975-ui-modal.mjs.map +1 -0
- package/fesm2022/area8975-ui-money.mjs +230 -0
- package/fesm2022/area8975-ui-money.mjs.map +1 -0
- package/fesm2022/area8975-ui-overlay.mjs +317 -0
- package/fesm2022/area8975-ui-overlay.mjs.map +1 -0
- package/fesm2022/area8975-ui-pagination.mjs +152 -0
- package/fesm2022/area8975-ui-pagination.mjs.map +1 -0
- package/fesm2022/area8975-ui-private.mjs +63 -0
- package/fesm2022/area8975-ui-private.mjs.map +1 -0
- package/fesm2022/area8975-ui-progress.mjs +307 -0
- package/fesm2022/area8975-ui-progress.mjs.map +1 -0
- package/fesm2022/area8975-ui-radio.mjs +199 -0
- package/fesm2022/area8975-ui-radio.mjs.map +1 -0
- package/fesm2022/area8975-ui-rich-text-editor.mjs +778 -0
- package/fesm2022/area8975-ui-rich-text-editor.mjs.map +1 -0
- package/fesm2022/area8975-ui-search.mjs +266 -0
- package/fesm2022/area8975-ui-search.mjs.map +1 -0
- package/fesm2022/area8975-ui-segmented.mjs +118 -0
- package/fesm2022/area8975-ui-segmented.mjs.map +1 -0
- package/fesm2022/area8975-ui-select.mjs +926 -0
- package/fesm2022/area8975-ui-select.mjs.map +1 -0
- package/fesm2022/area8975-ui-sidebar-group.mjs +60 -0
- package/fesm2022/area8975-ui-sidebar-group.mjs.map +1 -0
- package/fesm2022/area8975-ui-sidebar-item.mjs +107 -0
- package/fesm2022/area8975-ui-sidebar-item.mjs.map +1 -0
- package/fesm2022/area8975-ui-sidebar.mjs +109 -0
- package/fesm2022/area8975-ui-sidebar.mjs.map +1 -0
- package/fesm2022/area8975-ui-skeleton.mjs +116 -0
- package/fesm2022/area8975-ui-skeleton.mjs.map +1 -0
- package/fesm2022/area8975-ui-stat.mjs +55 -0
- package/fesm2022/area8975-ui-stat.mjs.map +1 -0
- package/fesm2022/area8975-ui-switch.mjs +132 -0
- package/fesm2022/area8975-ui-switch.mjs.map +1 -0
- package/fesm2022/area8975-ui-tab.mjs +217 -0
- package/fesm2022/area8975-ui-tab.mjs.map +1 -0
- package/fesm2022/area8975-ui-table-filters.mjs +499 -0
- package/fesm2022/area8975-ui-table-filters.mjs.map +1 -0
- package/fesm2022/area8975-ui-table.mjs +1237 -0
- package/fesm2022/area8975-ui-table.mjs.map +1 -0
- package/fesm2022/area8975-ui-textarea.mjs +375 -0
- package/fesm2022/area8975-ui-textarea.mjs.map +1 -0
- package/fesm2022/area8975-ui-theme.mjs +246 -0
- package/fesm2022/area8975-ui-theme.mjs.map +1 -0
- package/fesm2022/area8975-ui-time-select.mjs +170 -0
- package/fesm2022/area8975-ui-time-select.mjs.map +1 -0
- package/fesm2022/area8975-ui-toast.mjs +269 -0
- package/fesm2022/area8975-ui-toast.mjs.map +1 -0
- package/fesm2022/area8975-ui-toaster.mjs +117 -0
- package/fesm2022/area8975-ui-toaster.mjs.map +1 -0
- package/fesm2022/area8975-ui-tooltip.mjs +196 -0
- package/fesm2022/area8975-ui-tooltip.mjs.map +1 -0
- package/fesm2022/area8975-ui-user-menu.mjs +186 -0
- package/fesm2022/area8975-ui-user-menu.mjs.map +1 -0
- package/fesm2022/area8975-ui.mjs +0 -16269
- package/package.json +237 -1
- package/types/area8975-ui-alert.d.ts +25 -0
- package/types/area8975-ui-avatar.d.ts +40 -0
- package/types/area8975-ui-badge.d.ts +31 -0
- package/types/area8975-ui-button.d.ts +129 -0
- package/types/area8975-ui-calendar.d.ts +177 -0
- package/types/area8975-ui-card-header.d.ts +28 -0
- package/types/area8975-ui-card.d.ts +18 -0
- package/types/area8975-ui-chart-palette.d.ts +176 -0
- package/types/area8975-ui-charts.d.ts +747 -0
- package/types/area8975-ui-checkbox.d.ts +61 -0
- package/types/area8975-ui-colour.d.ts +31 -0
- package/types/area8975-ui-container.d.ts +5 -0
- package/types/area8975-ui-counter.d.ts +43 -0
- package/types/area8975-ui-date-range-picker.d.ts +132 -0
- package/types/area8975-ui-datepicker.d.ts +124 -0
- package/types/area8975-ui-disclosure.d.ts +79 -0
- package/types/area8975-ui-drawer.d.ts +25 -0
- package/types/area8975-ui-dropdown-button.d.ts +32 -0
- package/types/area8975-ui-dropdown-menu.d.ts +25 -0
- package/types/area8975-ui-dropdown.d.ts +56 -0
- package/types/area8975-ui-dropzone.d.ts +96 -0
- package/types/area8975-ui-field.d.ts +72 -0
- package/types/area8975-ui-file-input.d.ts +72 -0
- package/types/area8975-ui-file.d.ts +21 -0
- package/types/area8975-ui-format.d.ts +37 -0
- package/types/area8975-ui-input-addon.d.ts +10 -0
- package/types/area8975-ui-input-group.d.ts +18 -0
- package/types/area8975-ui-input.d.ts +224 -0
- package/types/area8975-ui-kpi.d.ts +36 -0
- package/types/area8975-ui-layout.d.ts +7 -0
- package/types/area8975-ui-loading.d.ts +16 -0
- package/types/area8975-ui-modal-close-btn.d.ts +14 -0
- package/types/area8975-ui-modal.d.ts +45 -0
- package/types/area8975-ui-money.d.ts +77 -0
- package/types/area8975-ui-overlay.d.ts +75 -0
- package/types/area8975-ui-pagination.d.ts +27 -0
- package/types/area8975-ui-private.d.ts +20 -0
- package/types/area8975-ui-progress.d.ts +127 -0
- package/types/area8975-ui-radio.d.ts +61 -0
- package/types/area8975-ui-rich-text-editor.d.ts +165 -0
- package/types/area8975-ui-search.d.ts +56 -0
- package/types/area8975-ui-segmented.d.ts +41 -0
- package/types/area8975-ui-select.d.ts +293 -0
- package/types/area8975-ui-sidebar-group.d.ts +15 -0
- package/types/area8975-ui-sidebar-item.d.ts +20 -0
- package/types/area8975-ui-sidebar.d.ts +16 -0
- package/types/area8975-ui-skeleton.d.ts +35 -0
- package/types/area8975-ui-stat.d.ts +13 -0
- package/types/area8975-ui-switch.d.ts +32 -0
- package/types/area8975-ui-tab.d.ts +45 -0
- package/types/area8975-ui-table-filters.d.ts +138 -0
- package/types/area8975-ui-table.d.ts +371 -0
- package/types/area8975-ui-textarea.d.ts +126 -0
- package/types/area8975-ui-theme.d.ts +61 -0
- package/types/area8975-ui-time-select.d.ts +35 -0
- package/types/area8975-ui-toast.d.ts +78 -0
- package/types/area8975-ui-toaster.d.ts +23 -0
- package/types/area8975-ui-tooltip.d.ts +47 -0
- package/types/area8975-ui-user-menu.d.ts +39 -0
- package/types/area8975-ui.d.ts +1 -4464
- 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":"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"}
|
|
@@ -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"}
|