ngx-com 0.0.21 → 0.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +137 -33
- package/fesm2022/ngx-com-components-alert.mjs +21 -11
- package/fesm2022/ngx-com-components-alert.mjs.map +1 -1
- package/fesm2022/ngx-com-components-avatar.mjs +9 -7
- package/fesm2022/ngx-com-components-avatar.mjs.map +1 -1
- package/fesm2022/ngx-com-components-button.mjs +1 -1
- package/fesm2022/ngx-com-components-button.mjs.map +1 -1
- package/fesm2022/ngx-com-components-calendar.mjs +27 -3112
- package/fesm2022/ngx-com-components-calendar.mjs.map +1 -1
- package/fesm2022/ngx-com-components-card.mjs +8 -8
- package/fesm2022/ngx-com-components-card.mjs.map +1 -1
- package/fesm2022/ngx-com-components-carousel.mjs +16 -4
- package/fesm2022/ngx-com-components-carousel.mjs.map +1 -1
- package/fesm2022/ngx-com-components-checkbox.mjs +1 -1
- package/fesm2022/ngx-com-components-checkbox.mjs.map +1 -1
- package/fesm2022/ngx-com-components-code-block.mjs +9 -9
- package/fesm2022/ngx-com-components-code-block.mjs.map +1 -1
- package/fesm2022/ngx-com-components-collapsible.mjs +15 -13
- package/fesm2022/ngx-com-components-collapsible.mjs.map +1 -1
- package/fesm2022/ngx-com-components-confirm.mjs +4 -4
- package/fesm2022/ngx-com-components-confirm.mjs.map +1 -1
- package/fesm2022/ngx-com-components-datepicker.mjs +2334 -0
- package/fesm2022/ngx-com-components-datepicker.mjs.map +1 -0
- package/fesm2022/ngx-com-components-dialog.mjs +47 -45
- package/fesm2022/ngx-com-components-dialog.mjs.map +1 -1
- package/fesm2022/ngx-com-components-dropdown.mjs +446 -340
- package/fesm2022/ngx-com-components-dropdown.mjs.map +1 -1
- package/fesm2022/ngx-com-components-empty-state.mjs +5 -3
- package/fesm2022/ngx-com-components-empty-state.mjs.map +1 -1
- package/fesm2022/ngx-com-components-form-field.mjs +11 -6
- package/fesm2022/ngx-com-components-form-field.mjs.map +1 -1
- package/fesm2022/ngx-com-components-icon-lucide.mjs +41 -0
- package/fesm2022/ngx-com-components-icon-lucide.mjs.map +1 -0
- package/fesm2022/ngx-com-components-icon.mjs +89 -61
- package/fesm2022/ngx-com-components-icon.mjs.map +1 -1
- package/fesm2022/ngx-com-components-item.mjs +14 -4
- package/fesm2022/ngx-com-components-item.mjs.map +1 -1
- package/fesm2022/ngx-com-components-menu.mjs +61 -69
- package/fesm2022/ngx-com-components-menu.mjs.map +1 -1
- package/fesm2022/ngx-com-components-native-control.mjs +170 -0
- package/fesm2022/ngx-com-components-native-control.mjs.map +1 -0
- package/fesm2022/ngx-com-components-paginator.mjs +11 -3
- package/fesm2022/ngx-com-components-paginator.mjs.map +1 -1
- package/fesm2022/ngx-com-components-popover.mjs +58 -33
- package/fesm2022/ngx-com-components-popover.mjs.map +1 -1
- package/fesm2022/ngx-com-components-radio.mjs +4 -4
- package/fesm2022/ngx-com-components-radio.mjs.map +1 -1
- package/fesm2022/ngx-com-components-segmented-control.mjs +6 -4
- package/fesm2022/ngx-com-components-segmented-control.mjs.map +1 -1
- package/fesm2022/ngx-com-components-sort.mjs +63 -57
- package/fesm2022/ngx-com-components-sort.mjs.map +1 -1
- package/fesm2022/ngx-com-components-spinner.mjs +6 -6
- package/fesm2022/ngx-com-components-spinner.mjs.map +1 -1
- package/fesm2022/ngx-com-components-switch.mjs +18 -9
- package/fesm2022/ngx-com-components-switch.mjs.map +1 -1
- package/fesm2022/ngx-com-components-table.mjs +23 -9
- package/fesm2022/ngx-com-components-table.mjs.map +1 -1
- package/fesm2022/ngx-com-components-tabs.mjs +81 -58
- package/fesm2022/ngx-com-components-tabs.mjs.map +1 -1
- package/fesm2022/ngx-com-components-timepicker.mjs +1048 -0
- package/fesm2022/ngx-com-components-timepicker.mjs.map +1 -0
- package/fesm2022/ngx-com-components-toast.mjs +18 -14
- package/fesm2022/ngx-com-components-toast.mjs.map +1 -1
- package/fesm2022/ngx-com-components-tooltip.mjs +5 -5
- package/fesm2022/ngx-com-components-tooltip.mjs.map +1 -1
- package/fesm2022/ngx-com-components.mjs +0 -13
- package/fesm2022/ngx-com-components.mjs.map +1 -1
- package/fesm2022/ngx-com-tokens.mjs +0 -8
- package/fesm2022/ngx-com-tokens.mjs.map +1 -1
- package/fesm2022/ngx-com-utils.mjs +13 -1
- package/fesm2022/ngx-com-utils.mjs.map +1 -1
- package/fesm2022/ngx-com.mjs +1 -1
- package/fesm2022/ngx-com.mjs.map +1 -1
- package/package.json +51 -8
- package/styles/animations.css +38 -0
- package/styles/candy.css +121 -0
- package/styles/dark.css +159 -0
- package/styles/forest.css +117 -0
- package/styles/ocean.css +117 -0
- package/styles/themes.css +7 -0
- package/styles/tokens.css +277 -0
- package/styles/utilities.css +16 -0
- package/types/ngx-com-components-alert.d.ts +14 -4
- package/types/ngx-com-components-avatar.d.ts +2 -0
- package/types/ngx-com-components-calendar.d.ts +3 -747
- package/types/ngx-com-components-card.d.ts +2 -2
- package/types/ngx-com-components-carousel.d.ts +11 -1
- package/types/ngx-com-components-code-block.d.ts +4 -4
- package/types/ngx-com-components-collapsible.d.ts +10 -2
- package/types/ngx-com-components-confirm.d.ts +2 -2
- package/types/ngx-com-components-datepicker.d.ts +623 -0
- package/types/ngx-com-components-dialog.d.ts +5 -2
- package/types/ngx-com-components-dropdown.d.ts +22 -4
- package/types/ngx-com-components-empty-state.d.ts +2 -0
- package/types/ngx-com-components-form-field.d.ts +4 -1
- package/types/ngx-com-components-icon-lucide.d.ts +32 -0
- package/types/ngx-com-components-icon.d.ts +49 -35
- package/types/ngx-com-components-item.d.ts +12 -2
- package/types/ngx-com-components-menu.d.ts +38 -38
- package/types/ngx-com-components-native-control.d.ts +99 -0
- package/types/ngx-com-components-paginator.d.ts +2 -0
- package/types/ngx-com-components-popover.d.ts +19 -12
- package/types/ngx-com-components-segmented-control.d.ts +3 -1
- package/types/ngx-com-components-sort.d.ts +13 -10
- package/types/ngx-com-components-switch.d.ts +7 -2
- package/types/ngx-com-components-table.d.ts +16 -2
- package/types/ngx-com-components-tabs.d.ts +46 -34
- package/types/ngx-com-components-timepicker.d.ts +273 -0
- package/types/ngx-com-components-toast.d.ts +4 -2
- package/types/ngx-com-components-tooltip.d.ts +1 -1
- package/types/ngx-com-components.d.ts +6 -7
- package/types/ngx-com-tokens.d.ts +5 -3
- package/types/ngx-com-utils.d.ts +11 -1
- package/types/ngx-com.d.ts +1 -1
|
@@ -12,6 +12,8 @@ import { cva } from 'class-variance-authority';
|
|
|
12
12
|
* inner content of each segment while the component manages the button,
|
|
13
13
|
* styling, and ARIA attributes.
|
|
14
14
|
*
|
|
15
|
+
* @tokens none
|
|
16
|
+
*
|
|
15
17
|
* @example Icon + text
|
|
16
18
|
* ```html
|
|
17
19
|
* <com-segmented-control [options]="viewOptions" [(value)]="currentView">
|
|
@@ -53,7 +55,7 @@ const segmentedControlContainerVariants = cva([
|
|
|
53
55
|
'rounded-pill',
|
|
54
56
|
'bg-muted',
|
|
55
57
|
'p-1',
|
|
56
|
-
'transition-colors duration-
|
|
58
|
+
'transition-colors duration-normal',
|
|
57
59
|
], {
|
|
58
60
|
variants: {
|
|
59
61
|
size: {
|
|
@@ -80,7 +82,7 @@ const segmentedControlSegmentVariants = cva([
|
|
|
80
82
|
'inline-flex items-center justify-center',
|
|
81
83
|
'rounded-pill',
|
|
82
84
|
'font-medium whitespace-nowrap select-none',
|
|
83
|
-
'transition-colors duration-
|
|
85
|
+
'transition-colors duration-normal',
|
|
84
86
|
'cursor-pointer',
|
|
85
87
|
'gap-1.5',
|
|
86
88
|
'focus-visible:outline-[1px] focus-visible:outline-offset-2 focus-visible:outline-ring',
|
|
@@ -229,7 +231,7 @@ const SEGMENT_DISABLED_CLASSES = 'bg-disabled text-disabled-foreground cursor-no
|
|
|
229
231
|
* <span>{{ option.label }}</span>
|
|
230
232
|
* <span
|
|
231
233
|
* class="ml-1.5 rounded-pill px-1.5 text-xs"
|
|
232
|
-
* [class]="active ? 'bg-accent-
|
|
234
|
+
* [class]="active ? 'bg-accent-subtle text-accent-subtle-foreground' : 'bg-muted text-muted-foreground'"
|
|
233
235
|
* >
|
|
234
236
|
* {{ option.value === 'open' ? openCount : closedCount }}
|
|
235
237
|
* </span>
|
|
@@ -377,7 +379,7 @@ class ComSegmentedControl {
|
|
|
377
379
|
*/
|
|
378
380
|
onKeydown(event, currentIndex) {
|
|
379
381
|
const opts = this.options();
|
|
380
|
-
let targetIndex
|
|
382
|
+
let targetIndex;
|
|
381
383
|
switch (event.key) {
|
|
382
384
|
case 'ArrowRight':
|
|
383
385
|
case 'ArrowDown':
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"ngx-com-components-segmented-control.mjs","sources":["../../../projects/com/components/segmented-control/segment-def.directive.ts","../../../projects/com/components/segmented-control/segmented-control.variants.ts","../../../projects/com/components/segmented-control/segmented-control.component.ts","../../../projects/com/components/segmented-control/index.ts","../../../projects/com/components/segmented-control/ngx-com-components-segmented-control.ts"],"sourcesContent":["import { Directive, TemplateRef, inject } from '@angular/core';\nimport type { SegmentOption } from './segmented-control.component';\n\n/**\n * Template context provided to custom segment templates.\n *\n * @example\n * ```html\n * <ng-template comSegmentDef let-option let-active=\"active\">\n * <com-icon [name]=\"option.value\" />\n * <span>{{ option.label }}</span>\n * </ng-template>\n * ```\n */\nexport interface SegmentTemplateContext<T = unknown> {\n /** The option object (default for `let-option`). */\n $implicit: SegmentOption<T>;\n /** Whether this segment is currently selected. */\n active: boolean;\n /** Whether this segment is disabled. */\n disabled: boolean;\n /** Position in the options list (0-indexed). */\n index: number;\n}\n\n/**\n * Directive to mark a custom template for segment content.\n *\n * The template receives a `SegmentTemplateContext` with the option data,\n * active state, disabled state, and index. Use this to customize the\n * inner content of each segment while the component manages the button,\n * styling, and ARIA attributes.\n *\n * @example Icon + text\n * ```html\n * <com-segmented-control [options]=\"viewOptions\" [(value)]=\"currentView\">\n * <ng-template comSegmentDef let-option let-active=\"active\">\n * <com-icon [name]=\"option.value\" size=\"sm\" />\n * <span>{{ option.label }}</span>\n * </ng-template>\n * </com-segmented-control>\n * ```\n *\n * @example Icon only (label used for accessibility)\n * ```html\n * <com-segmented-control [options]=\"alignmentOptions\" [(value)]=\"alignment\">\n * <ng-template comSegmentDef let-option>\n * <com-icon [name]=\"'align-' + option.value\" size=\"sm\" />\n * </ng-template>\n * </com-segmented-control>\n * ```\n */\n@Directive({\n selector: 'ng-template[comSegmentDef]',\n})\nexport class ComSegmentDef<T = unknown> {\n readonly templateRef: TemplateRef<SegmentTemplateContext<T>> = inject(TemplateRef);\n}\n","import { cva, type VariantProps } from 'class-variance-authority';\n\n// ─── Types ───\n\nexport type SegmentedControlSize = 'sm' | 'md' | 'lg';\nexport type SegmentedControlColor = 'primary' | 'accent' | 'muted';\nexport type SegmentedControlVariant = 'filled' | 'outline';\n\n// ─── Container Variants ───\n\n/**\n * CVA variants for the segmented control container (track).\n * Controls overall sizing, padding, and track background.\n */\nexport const segmentedControlContainerVariants: (props?: {\n size?: SegmentedControlSize;\n fullWidth?: boolean;\n}) => string = cva(\n [\n 'inline-flex items-center',\n 'rounded-pill',\n 'bg-muted',\n 'p-1',\n 'transition-colors duration-150',\n ],\n {\n variants: {\n size: {\n sm: 'gap-0.5',\n md: 'gap-1',\n lg: 'gap-1',\n },\n fullWidth: {\n true: 'w-full',\n false: '',\n },\n },\n defaultVariants: {\n size: 'md',\n fullWidth: false,\n },\n }\n);\n\n// ─── Segment Variants ───\n\n/**\n * CVA variants for individual segment buttons.\n * Controls per-segment sizing, typography, and active/inactive color states.\n */\nexport const segmentedControlSegmentVariants: (props?: {\n size?: SegmentedControlSize;\n color?: SegmentedControlColor;\n variant?: SegmentedControlVariant;\n active?: boolean;\n fullWidth?: boolean;\n}) => string = cva(\n [\n 'inline-flex items-center justify-center',\n 'rounded-pill',\n 'font-medium whitespace-nowrap select-none',\n 'transition-colors duration-150',\n 'cursor-pointer',\n 'gap-1.5',\n 'focus-visible:outline-[1px] focus-visible:outline-offset-2 focus-visible:outline-ring',\n ],\n {\n variants: {\n size: {\n sm: 'h-7 px-3 text-sm',\n md: 'h-8 px-4 text-sm',\n lg: 'h-10 px-5 text-base',\n },\n color: {\n primary: '',\n accent: '',\n muted: '',\n },\n variant: {\n filled: '',\n outline: 'bg-transparent',\n },\n active: {\n true: '',\n false: 'text-foreground',\n },\n fullWidth: {\n true: 'flex-1',\n false: '',\n },\n },\n compoundVariants: [\n // ─── Filled + Active ───\n {\n variant: 'filled',\n color: 'primary',\n active: true,\n class: 'bg-primary text-primary-foreground shadow-sm',\n },\n {\n variant: 'filled',\n color: 'accent',\n active: true,\n class: 'bg-accent text-accent-foreground shadow-sm',\n },\n {\n variant: 'filled',\n color: 'muted',\n active: true,\n class: 'bg-background text-foreground shadow-sm',\n },\n\n // ─── Filled + Inactive (hover) ───\n {\n variant: 'filled',\n active: false,\n class: 'hover:bg-muted-hover',\n },\n\n // ─── Outline + Active ───\n {\n variant: 'outline',\n color: 'primary',\n active: true,\n class: 'ring-2 ring-primary text-primary',\n },\n {\n variant: 'outline',\n color: 'accent',\n active: true,\n class: 'ring-2 ring-accent text-accent',\n },\n {\n variant: 'outline',\n color: 'muted',\n active: true,\n class: 'ring-2 ring-border text-foreground',\n },\n\n // ─── Outline + Inactive (hover) ───\n {\n variant: 'outline',\n active: false,\n class: 'hover:bg-muted-hover',\n },\n ],\n defaultVariants: {\n size: 'md',\n color: 'primary',\n variant: 'filled',\n active: false,\n fullWidth: false,\n },\n }\n);\n\n// ─── Disabled Segment Classes ───\n\n/**\n * Classes to apply when a segment is disabled.\n * Separate from CVA to avoid complex variant combinations.\n */\nexport const SEGMENT_DISABLED_CLASSES =\n 'bg-disabled text-disabled-foreground cursor-not-allowed hover:bg-disabled';\n\n// ─── Variant Types ───\n\nexport type SegmentedControlContainerVariants = VariantProps<typeof segmentedControlContainerVariants>;\nexport type SegmentedControlSegmentVariants = VariantProps<typeof segmentedControlSegmentVariants>;\n","import {\n booleanAttribute,\n ChangeDetectionStrategy,\n Component,\n computed,\n contentChild,\n ElementRef,\n input,\n model,\n viewChildren,\n ViewEncapsulation,\n} from '@angular/core';\nimport type { InputSignal, InputSignalWithTransform, ModelSignal, Signal } from '@angular/core';\nimport { NgTemplateOutlet } from '@angular/common';\nimport { mergeClasses } from 'ngx-com/utils';\nimport { ComSegmentDef, type SegmentTemplateContext } from './segment-def.directive';\nimport {\n segmentedControlContainerVariants,\n segmentedControlSegmentVariants,\n SEGMENT_DISABLED_CLASSES,\n} from './segmented-control.variants';\nimport type {\n SegmentedControlSize,\n SegmentedControlColor,\n SegmentedControlVariant,\n} from './segmented-control.variants';\n\n/**\n * Represents a single option in the segmented control.\n */\nexport interface SegmentOption<T = unknown> {\n /** The value associated with this option. */\n value: T;\n /** Display label (also used as aria-label fallback for custom templates). */\n label: string;\n /** Whether this option is disabled. */\n disabled?: boolean | undefined;\n}\n\n/**\n * Segmented control component — a horizontal group of mutually exclusive options\n * where one is always selected. Think of it as a styled radio group in pill form.\n *\n * Supports two rendering modes:\n * - **Simple mode**: Plain text labels from the `label` property\n * - **Custom template mode**: Full control via `ng-template[comSegmentDef]`\n *\n * @tokens `--color-primary`, `--color-primary-foreground`,\n * `--color-accent`, `--color-accent-foreground`,\n * `--color-muted`, `--color-muted-foreground`, `--color-muted-hover`,\n * `--color-background`, `--color-foreground`,\n * `--color-disabled`, `--color-disabled-foreground`,\n * `--color-border`, `--color-ring`\n *\n * @example Basic two-option toggle\n * ```html\n * <com-segmented-control\n * [options]=\"[\n * { value: 'admin', label: 'Admin' },\n * { value: 'user', label: 'User' }\n * ]\"\n * [(value)]=\"selectedRole\"\n * />\n * ```\n *\n * @example Multiple options with variants\n * ```html\n * <com-segmented-control\n * [options]=\"viewOptions\"\n * [(value)]=\"currentView\"\n * color=\"primary\"\n * size=\"sm\"\n * />\n * ```\n *\n * @example Custom template with icons\n * ```html\n * <com-segmented-control [options]=\"viewOptions\" [(value)]=\"currentView\" color=\"primary\">\n * <ng-template comSegmentDef let-option let-active=\"active\">\n * <com-icon [name]=\"option.value === 'grid' ? 'grid' : 'list'\" size=\"sm\" />\n * <span>{{ option.label }}</span>\n * </ng-template>\n * </com-segmented-control>\n * ```\n *\n * @example Custom template with badges\n * ```html\n * <com-segmented-control [options]=\"statusOptions\" [(value)]=\"statusFilter\" color=\"accent\">\n * <ng-template comSegmentDef let-option let-active=\"active\">\n * <span>{{ option.label }}</span>\n * <span\n * class=\"ml-1.5 rounded-pill px-1.5 text-xs\"\n * [class]=\"active ? 'bg-accent-foreground/20 text-accent-foreground' : 'bg-muted text-muted-foreground'\"\n * >\n * {{ option.value === 'open' ? openCount : closedCount }}\n * </span>\n * </ng-template>\n * </com-segmented-control>\n * ```\n *\n * @example Icon only (label used for accessibility)\n * ```html\n * <com-segmented-control\n * [options]=\"[\n * { value: 'left', label: 'Align left' },\n * { value: 'center', label: 'Align center' },\n * { value: 'right', label: 'Align right' }\n * ]\"\n * [(value)]=\"alignment\"\n * size=\"sm\"\n * >\n * <ng-template comSegmentDef let-option>\n * <com-icon [name]=\"'align-' + option.value\" size=\"sm\" />\n * </ng-template>\n * </com-segmented-control>\n * ```\n *\n * @example Full width + outline variant\n * ```html\n * <com-segmented-control\n * [options]=\"plans\"\n * [(value)]=\"selectedPlan\"\n * variant=\"outline\"\n * color=\"primary\"\n * [fullWidth]=\"true\"\n * />\n * ```\n *\n * @example Disabled options\n * ```html\n * <com-segmented-control\n * [options]=\"[\n * { value: 'free', label: 'Free' },\n * { value: 'pro', label: 'Pro' },\n * { value: 'enterprise', label: 'Enterprise', disabled: true }\n * ]\"\n * [(value)]=\"plan\"\n * color=\"primary\"\n * size=\"lg\"\n * />\n * ```\n */\n@Component({\n selector: 'com-segmented-control',\n exportAs: 'comSegmentedControl',\n template: `\n <div\n role=\"radiogroup\"\n [attr.aria-label]=\"ariaLabel()\"\n [class]=\"containerClasses()\"\n >\n @for (option of options(); track option.value; let i = $index) {\n <button\n #segmentButton\n type=\"button\"\n role=\"radio\"\n [attr.aria-checked]=\"isActive(option)\"\n [attr.aria-label]=\"customTemplate() ? option.label : null\"\n [attr.aria-disabled]=\"option.disabled || null\"\n [disabled]=\"option.disabled\"\n [tabindex]=\"tabIndexFor(i)\"\n [class]=\"segmentClasses(option)\"\n (click)=\"select(option)\"\n (keydown)=\"onKeydown($event, i)\"\n >\n @if (customTemplate(); as tpl) {\n <ng-container\n [ngTemplateOutlet]=\"tpl.templateRef\"\n [ngTemplateOutletContext]=\"getTemplateContext(option, i)\"\n />\n } @else {\n {{ option.label }}\n }\n </button>\n }\n </div>\n `,\n styles: `\n com-segmented-control {\n display: inline-block;\n }\n com-segmented-control[fullWidth] {\n display: block;\n }\n `,\n imports: [NgTemplateOutlet],\n changeDetection: ChangeDetectionStrategy.OnPush,\n encapsulation: ViewEncapsulation.None,\n host: {\n class: 'com-segmented-control',\n '[attr.fullWidth]': 'fullWidth() || null',\n },\n})\nexport class ComSegmentedControl<T = unknown> {\n // ─── View Children ───\n\n /** References to all segment buttons for focus management. */\n private readonly segmentButtons: Signal<readonly ElementRef<HTMLButtonElement>[]> =\n viewChildren<ElementRef<HTMLButtonElement>>('segmentButton');\n\n // ─── Inputs ───\n\n /** The list of options to display. */\n readonly options: InputSignal<SegmentOption<T>[]> = input.required<SegmentOption<T>[]>();\n\n /** Currently selected value. Two-way bindable with `[(value)]`. */\n readonly value: ModelSignal<T | undefined> = model<T | undefined>(undefined);\n\n /** Controls segment height, padding, and font size. */\n readonly size: InputSignal<SegmentedControlSize> = input<SegmentedControlSize>('md');\n\n /** Color scheme for the active segment. */\n readonly color: InputSignal<SegmentedControlColor> = input<SegmentedControlColor>('primary');\n\n /** Visual variant: filled (solid background) or outline (ring border). */\n readonly variant: InputSignal<SegmentedControlVariant> = input<SegmentedControlVariant>('filled');\n\n /** When true, segments stretch equally to fill available width. */\n readonly fullWidth: InputSignalWithTransform<boolean, unknown> = input(false, {\n transform: booleanAttribute,\n });\n\n /** Accessible label for the radiogroup container. */\n readonly ariaLabel: InputSignal<string | null> = input<string | null>(null, {\n alias: 'aria-label',\n });\n\n /** Custom CSS classes to merge with container classes. */\n readonly userClass: InputSignal<string> = input('', { alias: 'class' });\n\n // ─── Content Child ───\n\n /** Optional custom template for segment content. */\n readonly customTemplate: Signal<ComSegmentDef<T> | undefined> = contentChild<ComSegmentDef<T>>(ComSegmentDef);\n\n // ─── Computed ───\n\n /** Classes for the container/track element. */\n protected readonly containerClasses: Signal<string> = computed(() =>\n mergeClasses(\n segmentedControlContainerVariants({\n size: this.size(),\n fullWidth: this.fullWidth(),\n }),\n this.userClass()\n )\n );\n\n // ─── Public Methods ───\n\n /**\n * Checks if the given option is currently selected.\n */\n isActive(option: SegmentOption<T>): boolean {\n return this.value() === option.value;\n }\n\n /**\n * Selects the given option (if not disabled).\n */\n select(option: SegmentOption<T>): void {\n if (option.disabled) {\n return;\n }\n this.value.set(option.value);\n }\n\n /**\n * Returns the tabindex for a segment at the given index.\n * Implements roving tabindex: only the selected (or first focusable) segment has tabindex=\"0\".\n */\n tabIndexFor(index: number): number {\n const opts = this.options();\n const currentValue = this.value();\n\n // If current value matches this option, it gets tabindex=\"0\"\n if (opts[index]?.value === currentValue) {\n return 0;\n }\n\n // If no value is selected, first non-disabled option gets tabindex=\"0\"\n if (currentValue === undefined) {\n const firstFocusableIndex = opts.findIndex((o) => !o.disabled);\n return index === firstFocusableIndex ? 0 : -1;\n }\n\n return -1;\n }\n\n /**\n * Returns computed classes for a segment button.\n */\n segmentClasses(option: SegmentOption<T>): string {\n const active = this.isActive(option);\n const baseClasses = segmentedControlSegmentVariants({\n size: this.size(),\n color: this.color(),\n variant: this.variant(),\n active,\n fullWidth: this.fullWidth(),\n });\n\n if (option.disabled) {\n return mergeClasses(baseClasses, SEGMENT_DISABLED_CLASSES);\n }\n\n return baseClasses;\n }\n\n /**\n * Builds the template context for custom templates.\n */\n getTemplateContext(option: SegmentOption<T>, index: number): SegmentTemplateContext<T> {\n return {\n $implicit: option,\n active: this.isActive(option),\n disabled: !!option.disabled,\n index,\n };\n }\n\n /**\n * Handles keyboard navigation for the segmented control.\n * Implements ARIA radiogroup keyboard patterns.\n */\n onKeydown(event: KeyboardEvent, currentIndex: number): void {\n const opts = this.options();\n let targetIndex: number | null = null;\n\n switch (event.key) {\n case 'ArrowRight':\n case 'ArrowDown':\n targetIndex = this.findNextFocusableIndex(currentIndex, 1);\n break;\n case 'ArrowLeft':\n case 'ArrowUp':\n targetIndex = this.findNextFocusableIndex(currentIndex, -1);\n break;\n case 'Home':\n targetIndex = this.findFirstFocusableIndex();\n break;\n case 'End':\n targetIndex = this.findLastFocusableIndex();\n break;\n default:\n return;\n }\n\n if (targetIndex !== null && targetIndex !== currentIndex) {\n event.preventDefault();\n const targetOption = opts[targetIndex];\n if (targetOption) {\n this.select(targetOption);\n this.focusSegmentAt(targetIndex);\n }\n }\n }\n\n // ─── Private Methods ───\n\n /**\n * Finds the next focusable (non-disabled) option index in the given direction.\n * Wraps around to the beginning/end of the list.\n */\n private findNextFocusableIndex(currentIndex: number, direction: 1 | -1): number | null {\n const opts = this.options();\n const length = opts.length;\n\n if (length === 0) {\n return null;\n }\n\n let index = currentIndex;\n for (let i = 0; i < length; i++) {\n index = (index + direction + length) % length;\n if (!opts[index]?.disabled) {\n return index;\n }\n }\n\n return null;\n }\n\n /**\n * Finds the first focusable (non-disabled) option index.\n */\n private findFirstFocusableIndex(): number | null {\n const opts = this.options();\n const index = opts.findIndex((o) => !o.disabled);\n return index >= 0 ? index : null;\n }\n\n /**\n * Finds the last focusable (non-disabled) option index.\n */\n private findLastFocusableIndex(): number | null {\n const opts = this.options();\n for (let i = opts.length - 1; i >= 0; i--) {\n if (!opts[i]?.disabled) {\n return i;\n }\n }\n return null;\n }\n\n /**\n * Focuses the segment button at the given index.\n */\n private focusSegmentAt(index: number): void {\n const button = this.segmentButtons()[index];\n if (button) {\n button.nativeElement.focus();\n }\n }\n}\n","// Public API for the segmented-control component\n\n// Main component\nexport { ComSegmentedControl } from './segmented-control.component';\nexport type { SegmentOption } from './segmented-control.component';\n\n// Directive\nexport { ComSegmentDef } from './segment-def.directive';\nexport type { SegmentTemplateContext } from './segment-def.directive';\n\n// Variants\nexport {\n segmentedControlContainerVariants,\n segmentedControlSegmentVariants,\n SEGMENT_DISABLED_CLASSES,\n} from './segmented-control.variants';\n\nexport type {\n SegmentedControlSize,\n SegmentedControlColor,\n SegmentedControlVariant,\n SegmentedControlContainerVariants,\n SegmentedControlSegmentVariants,\n} from './segmented-control.variants';\n","/**\n * Generated bundle index. Do not edit.\n */\n\nexport * from './index';\n"],"names":[],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"ngx-com-components-segmented-control.mjs","sources":["../../../projects/com/components/segmented-control/segment-def.directive.ts","../../../projects/com/components/segmented-control/segmented-control.variants.ts","../../../projects/com/components/segmented-control/segmented-control.component.ts","../../../projects/com/components/segmented-control/index.ts","../../../projects/com/components/segmented-control/ngx-com-components-segmented-control.ts"],"sourcesContent":["import { Directive, TemplateRef, inject } from '@angular/core';\nimport type { SegmentOption } from './segmented-control.component';\n\n/**\n * Template context provided to custom segment templates.\n *\n * @example\n * ```html\n * <ng-template comSegmentDef let-option let-active=\"active\">\n * <com-icon [name]=\"option.value\" />\n * <span>{{ option.label }}</span>\n * </ng-template>\n * ```\n */\nexport interface SegmentTemplateContext<T = unknown> {\n /** The option object (default for `let-option`). */\n $implicit: SegmentOption<T>;\n /** Whether this segment is currently selected. */\n active: boolean;\n /** Whether this segment is disabled. */\n disabled: boolean;\n /** Position in the options list (0-indexed). */\n index: number;\n}\n\n/**\n * Directive to mark a custom template for segment content.\n *\n * The template receives a `SegmentTemplateContext` with the option data,\n * active state, disabled state, and index. Use this to customize the\n * inner content of each segment while the component manages the button,\n * styling, and ARIA attributes.\n *\n * @tokens none\n *\n * @example Icon + text\n * ```html\n * <com-segmented-control [options]=\"viewOptions\" [(value)]=\"currentView\">\n * <ng-template comSegmentDef let-option let-active=\"active\">\n * <com-icon [name]=\"option.value\" size=\"sm\" />\n * <span>{{ option.label }}</span>\n * </ng-template>\n * </com-segmented-control>\n * ```\n *\n * @example Icon only (label used for accessibility)\n * ```html\n * <com-segmented-control [options]=\"alignmentOptions\" [(value)]=\"alignment\">\n * <ng-template comSegmentDef let-option>\n * <com-icon [name]=\"'align-' + option.value\" size=\"sm\" />\n * </ng-template>\n * </com-segmented-control>\n * ```\n */\n@Directive({\n selector: 'ng-template[comSegmentDef]',\n})\nexport class ComSegmentDef<T = unknown> {\n readonly templateRef: TemplateRef<SegmentTemplateContext<T>> = inject(TemplateRef);\n}\n","import { cva, type VariantProps } from 'class-variance-authority';\n\n// ─── Types ───\n\nexport type SegmentedControlSize = 'sm' | 'md' | 'lg';\nexport type SegmentedControlColor = 'primary' | 'accent' | 'muted';\nexport type SegmentedControlVariant = 'filled' | 'outline';\n\n// ─── Container Variants ───\n\n/**\n * CVA variants for the segmented control container (track).\n * Controls overall sizing, padding, and track background.\n */\nexport const segmentedControlContainerVariants: (props?: {\n size?: SegmentedControlSize;\n fullWidth?: boolean;\n}) => string = cva(\n [\n 'inline-flex items-center',\n 'rounded-pill',\n 'bg-muted',\n 'p-1',\n 'transition-colors duration-normal',\n ],\n {\n variants: {\n size: {\n sm: 'gap-0.5',\n md: 'gap-1',\n lg: 'gap-1',\n },\n fullWidth: {\n true: 'w-full',\n false: '',\n },\n },\n defaultVariants: {\n size: 'md',\n fullWidth: false,\n },\n }\n);\n\n// ─── Segment Variants ───\n\n/**\n * CVA variants for individual segment buttons.\n * Controls per-segment sizing, typography, and active/inactive color states.\n */\nexport const segmentedControlSegmentVariants: (props?: {\n size?: SegmentedControlSize;\n color?: SegmentedControlColor;\n variant?: SegmentedControlVariant;\n active?: boolean;\n fullWidth?: boolean;\n}) => string = cva(\n [\n 'inline-flex items-center justify-center',\n 'rounded-pill',\n 'font-medium whitespace-nowrap select-none',\n 'transition-colors duration-normal',\n 'cursor-pointer',\n 'gap-1.5',\n 'focus-visible:outline-[1px] focus-visible:outline-offset-2 focus-visible:outline-ring',\n ],\n {\n variants: {\n size: {\n sm: 'h-7 px-3 text-sm',\n md: 'h-8 px-4 text-sm',\n lg: 'h-10 px-5 text-base',\n },\n color: {\n primary: '',\n accent: '',\n muted: '',\n },\n variant: {\n filled: '',\n outline: 'bg-transparent',\n },\n active: {\n true: '',\n false: 'text-foreground',\n },\n fullWidth: {\n true: 'flex-1',\n false: '',\n },\n },\n compoundVariants: [\n // ─── Filled + Active ───\n {\n variant: 'filled',\n color: 'primary',\n active: true,\n class: 'bg-primary text-primary-foreground shadow-sm',\n },\n {\n variant: 'filled',\n color: 'accent',\n active: true,\n class: 'bg-accent text-accent-foreground shadow-sm',\n },\n {\n variant: 'filled',\n color: 'muted',\n active: true,\n class: 'bg-background text-foreground shadow-sm',\n },\n\n // ─── Filled + Inactive (hover) ───\n {\n variant: 'filled',\n active: false,\n class: 'hover:bg-muted-hover',\n },\n\n // ─── Outline + Active ───\n {\n variant: 'outline',\n color: 'primary',\n active: true,\n class: 'ring-2 ring-primary text-primary',\n },\n {\n variant: 'outline',\n color: 'accent',\n active: true,\n class: 'ring-2 ring-accent text-accent',\n },\n {\n variant: 'outline',\n color: 'muted',\n active: true,\n class: 'ring-2 ring-border text-foreground',\n },\n\n // ─── Outline + Inactive (hover) ───\n {\n variant: 'outline',\n active: false,\n class: 'hover:bg-muted-hover',\n },\n ],\n defaultVariants: {\n size: 'md',\n color: 'primary',\n variant: 'filled',\n active: false,\n fullWidth: false,\n },\n }\n);\n\n// ─── Disabled Segment Classes ───\n\n/**\n * Classes to apply when a segment is disabled.\n * Separate from CVA to avoid complex variant combinations.\n */\nexport const SEGMENT_DISABLED_CLASSES =\n 'bg-disabled text-disabled-foreground cursor-not-allowed hover:bg-disabled';\n\n// ─── Variant Types ───\n\nexport type SegmentedControlContainerVariants = VariantProps<typeof segmentedControlContainerVariants>;\nexport type SegmentedControlSegmentVariants = VariantProps<typeof segmentedControlSegmentVariants>;\n","import {\n booleanAttribute,\n ChangeDetectionStrategy,\n Component,\n computed,\n contentChild,\n ElementRef,\n input,\n model,\n viewChildren,\n ViewEncapsulation,\n} from '@angular/core';\nimport type { InputSignal, InputSignalWithTransform, ModelSignal, Signal } from '@angular/core';\nimport { NgTemplateOutlet } from '@angular/common';\nimport { mergeClasses } from 'ngx-com/utils';\nimport { ComSegmentDef, type SegmentTemplateContext } from './segment-def.directive';\nimport {\n segmentedControlContainerVariants,\n segmentedControlSegmentVariants,\n SEGMENT_DISABLED_CLASSES,\n} from './segmented-control.variants';\nimport type {\n SegmentedControlSize,\n SegmentedControlColor,\n SegmentedControlVariant,\n} from './segmented-control.variants';\n\n/**\n * Represents a single option in the segmented control.\n */\nexport interface SegmentOption<T = unknown> {\n /** The value associated with this option. */\n value: T;\n /** Display label (also used as aria-label fallback for custom templates). */\n label: string;\n /** Whether this option is disabled. */\n disabled?: boolean | undefined;\n}\n\n/**\n * Segmented control component — a horizontal group of mutually exclusive options\n * where one is always selected. Think of it as a styled radio group in pill form.\n *\n * Supports two rendering modes:\n * - **Simple mode**: Plain text labels from the `label` property\n * - **Custom template mode**: Full control via `ng-template[comSegmentDef]`\n *\n * @tokens `--color-primary`, `--color-primary-foreground`,\n * `--color-accent`, `--color-accent-foreground`,\n * `--color-muted`, `--color-muted-foreground`, `--color-muted-hover`,\n * `--color-background`, `--color-foreground`,\n * `--color-disabled`, `--color-disabled-foreground`,\n * `--color-border`, `--color-ring`\n *\n * @example Basic two-option toggle\n * ```html\n * <com-segmented-control\n * [options]=\"[\n * { value: 'admin', label: 'Admin' },\n * { value: 'user', label: 'User' }\n * ]\"\n * [(value)]=\"selectedRole\"\n * />\n * ```\n *\n * @example Multiple options with variants\n * ```html\n * <com-segmented-control\n * [options]=\"viewOptions\"\n * [(value)]=\"currentView\"\n * color=\"primary\"\n * size=\"sm\"\n * />\n * ```\n *\n * @example Custom template with icons\n * ```html\n * <com-segmented-control [options]=\"viewOptions\" [(value)]=\"currentView\" color=\"primary\">\n * <ng-template comSegmentDef let-option let-active=\"active\">\n * <com-icon [name]=\"option.value === 'grid' ? 'grid' : 'list'\" size=\"sm\" />\n * <span>{{ option.label }}</span>\n * </ng-template>\n * </com-segmented-control>\n * ```\n *\n * @example Custom template with badges\n * ```html\n * <com-segmented-control [options]=\"statusOptions\" [(value)]=\"statusFilter\" color=\"accent\">\n * <ng-template comSegmentDef let-option let-active=\"active\">\n * <span>{{ option.label }}</span>\n * <span\n * class=\"ml-1.5 rounded-pill px-1.5 text-xs\"\n * [class]=\"active ? 'bg-accent-subtle text-accent-subtle-foreground' : 'bg-muted text-muted-foreground'\"\n * >\n * {{ option.value === 'open' ? openCount : closedCount }}\n * </span>\n * </ng-template>\n * </com-segmented-control>\n * ```\n *\n * @example Icon only (label used for accessibility)\n * ```html\n * <com-segmented-control\n * [options]=\"[\n * { value: 'left', label: 'Align left' },\n * { value: 'center', label: 'Align center' },\n * { value: 'right', label: 'Align right' }\n * ]\"\n * [(value)]=\"alignment\"\n * size=\"sm\"\n * >\n * <ng-template comSegmentDef let-option>\n * <com-icon [name]=\"'align-' + option.value\" size=\"sm\" />\n * </ng-template>\n * </com-segmented-control>\n * ```\n *\n * @example Full width + outline variant\n * ```html\n * <com-segmented-control\n * [options]=\"plans\"\n * [(value)]=\"selectedPlan\"\n * variant=\"outline\"\n * color=\"primary\"\n * [fullWidth]=\"true\"\n * />\n * ```\n *\n * @example Disabled options\n * ```html\n * <com-segmented-control\n * [options]=\"[\n * { value: 'free', label: 'Free' },\n * { value: 'pro', label: 'Pro' },\n * { value: 'enterprise', label: 'Enterprise', disabled: true }\n * ]\"\n * [(value)]=\"plan\"\n * color=\"primary\"\n * size=\"lg\"\n * />\n * ```\n */\n@Component({\n selector: 'com-segmented-control',\n exportAs: 'comSegmentedControl',\n template: `\n <div\n role=\"radiogroup\"\n [attr.aria-label]=\"ariaLabel()\"\n [class]=\"containerClasses()\"\n >\n @for (option of options(); track option.value; let i = $index) {\n <button\n #segmentButton\n type=\"button\"\n role=\"radio\"\n [attr.aria-checked]=\"isActive(option)\"\n [attr.aria-label]=\"customTemplate() ? option.label : null\"\n [attr.aria-disabled]=\"option.disabled || null\"\n [disabled]=\"option.disabled\"\n [tabindex]=\"tabIndexFor(i)\"\n [class]=\"segmentClasses(option)\"\n (click)=\"select(option)\"\n (keydown)=\"onKeydown($event, i)\"\n >\n @if (customTemplate(); as tpl) {\n <ng-container\n [ngTemplateOutlet]=\"tpl.templateRef\"\n [ngTemplateOutletContext]=\"getTemplateContext(option, i)\"\n />\n } @else {\n {{ option.label }}\n }\n </button>\n }\n </div>\n `,\n styles: `\n com-segmented-control {\n display: inline-block;\n }\n com-segmented-control[fullWidth] {\n display: block;\n }\n `,\n imports: [NgTemplateOutlet],\n changeDetection: ChangeDetectionStrategy.OnPush,\n encapsulation: ViewEncapsulation.None,\n host: {\n class: 'com-segmented-control',\n '[attr.fullWidth]': 'fullWidth() || null',\n },\n})\nexport class ComSegmentedControl<T = unknown> {\n // ─── View Children ───\n\n /** References to all segment buttons for focus management. */\n private readonly segmentButtons: Signal<readonly ElementRef<HTMLButtonElement>[]> =\n viewChildren<ElementRef<HTMLButtonElement>>('segmentButton');\n\n // ─── Inputs ───\n\n /** The list of options to display. */\n readonly options: InputSignal<SegmentOption<T>[]> = input.required<SegmentOption<T>[]>();\n\n /** Currently selected value. Two-way bindable with `[(value)]`. */\n readonly value: ModelSignal<T | undefined> = model<T | undefined>(undefined);\n\n /** Controls segment height, padding, and font size. */\n readonly size: InputSignal<SegmentedControlSize> = input<SegmentedControlSize>('md');\n\n /** Color scheme for the active segment. */\n readonly color: InputSignal<SegmentedControlColor> = input<SegmentedControlColor>('primary');\n\n /** Visual variant: filled (solid background) or outline (ring border). */\n readonly variant: InputSignal<SegmentedControlVariant> = input<SegmentedControlVariant>('filled');\n\n /** When true, segments stretch equally to fill available width. */\n readonly fullWidth: InputSignalWithTransform<boolean, unknown> = input(false, {\n transform: booleanAttribute,\n });\n\n /** Accessible label for the radiogroup container. */\n readonly ariaLabel: InputSignal<string | null> = input<string | null>(null, {\n alias: 'aria-label',\n });\n\n /** Custom CSS classes to merge with container classes. */\n readonly userClass: InputSignal<string> = input('', { alias: 'class' });\n\n // ─── Content Child ───\n\n /** Optional custom template for segment content. */\n readonly customTemplate: Signal<ComSegmentDef<T> | undefined> = contentChild<ComSegmentDef<T>>(ComSegmentDef);\n\n // ─── Computed ───\n\n /** Classes for the container/track element. */\n protected readonly containerClasses: Signal<string> = computed(() =>\n mergeClasses(\n segmentedControlContainerVariants({\n size: this.size(),\n fullWidth: this.fullWidth(),\n }),\n this.userClass()\n )\n );\n\n // ─── Public Methods ───\n\n /**\n * Checks if the given option is currently selected.\n */\n isActive(option: SegmentOption<T>): boolean {\n return this.value() === option.value;\n }\n\n /**\n * Selects the given option (if not disabled).\n */\n select(option: SegmentOption<T>): void {\n if (option.disabled) {\n return;\n }\n this.value.set(option.value);\n }\n\n /**\n * Returns the tabindex for a segment at the given index.\n * Implements roving tabindex: only the selected (or first focusable) segment has tabindex=\"0\".\n */\n tabIndexFor(index: number): number {\n const opts = this.options();\n const currentValue = this.value();\n\n // If current value matches this option, it gets tabindex=\"0\"\n if (opts[index]?.value === currentValue) {\n return 0;\n }\n\n // If no value is selected, first non-disabled option gets tabindex=\"0\"\n if (currentValue === undefined) {\n const firstFocusableIndex = opts.findIndex((o) => !o.disabled);\n return index === firstFocusableIndex ? 0 : -1;\n }\n\n return -1;\n }\n\n /**\n * Returns computed classes for a segment button.\n */\n segmentClasses(option: SegmentOption<T>): string {\n const active = this.isActive(option);\n const baseClasses = segmentedControlSegmentVariants({\n size: this.size(),\n color: this.color(),\n variant: this.variant(),\n active,\n fullWidth: this.fullWidth(),\n });\n\n if (option.disabled) {\n return mergeClasses(baseClasses, SEGMENT_DISABLED_CLASSES);\n }\n\n return baseClasses;\n }\n\n /**\n * Builds the template context for custom templates.\n */\n getTemplateContext(option: SegmentOption<T>, index: number): SegmentTemplateContext<T> {\n return {\n $implicit: option,\n active: this.isActive(option),\n disabled: !!option.disabled,\n index,\n };\n }\n\n /**\n * Handles keyboard navigation for the segmented control.\n * Implements ARIA radiogroup keyboard patterns.\n */\n onKeydown(event: KeyboardEvent, currentIndex: number): void {\n const opts = this.options();\n let targetIndex: number | null;\n\n switch (event.key) {\n case 'ArrowRight':\n case 'ArrowDown':\n targetIndex = this.findNextFocusableIndex(currentIndex, 1);\n break;\n case 'ArrowLeft':\n case 'ArrowUp':\n targetIndex = this.findNextFocusableIndex(currentIndex, -1);\n break;\n case 'Home':\n targetIndex = this.findFirstFocusableIndex();\n break;\n case 'End':\n targetIndex = this.findLastFocusableIndex();\n break;\n default:\n return;\n }\n\n if (targetIndex !== null && targetIndex !== currentIndex) {\n event.preventDefault();\n const targetOption = opts[targetIndex];\n if (targetOption) {\n this.select(targetOption);\n this.focusSegmentAt(targetIndex);\n }\n }\n }\n\n // ─── Private Methods ───\n\n /**\n * Finds the next focusable (non-disabled) option index in the given direction.\n * Wraps around to the beginning/end of the list.\n */\n private findNextFocusableIndex(currentIndex: number, direction: 1 | -1): number | null {\n const opts = this.options();\n const length = opts.length;\n\n if (length === 0) {\n return null;\n }\n\n let index = currentIndex;\n for (let i = 0; i < length; i++) {\n index = (index + direction + length) % length;\n if (!opts[index]?.disabled) {\n return index;\n }\n }\n\n return null;\n }\n\n /**\n * Finds the first focusable (non-disabled) option index.\n */\n private findFirstFocusableIndex(): number | null {\n const opts = this.options();\n const index = opts.findIndex((o) => !o.disabled);\n return index >= 0 ? index : null;\n }\n\n /**\n * Finds the last focusable (non-disabled) option index.\n */\n private findLastFocusableIndex(): number | null {\n const opts = this.options();\n for (let i = opts.length - 1; i >= 0; i--) {\n if (!opts[i]?.disabled) {\n return i;\n }\n }\n return null;\n }\n\n /**\n * Focuses the segment button at the given index.\n */\n private focusSegmentAt(index: number): void {\n const button = this.segmentButtons()[index];\n if (button) {\n button.nativeElement.focus();\n }\n }\n}\n","// Public API for the segmented-control component\n\n// Main component\nexport { ComSegmentedControl } from './segmented-control.component';\nexport type { SegmentOption } from './segmented-control.component';\n\n// Directive\nexport { ComSegmentDef } from './segment-def.directive';\nexport type { SegmentTemplateContext } from './segment-def.directive';\n\n// Variants\nexport {\n segmentedControlContainerVariants,\n segmentedControlSegmentVariants,\n SEGMENT_DISABLED_CLASSES,\n} from './segmented-control.variants';\n\nexport type {\n SegmentedControlSize,\n SegmentedControlColor,\n SegmentedControlVariant,\n SegmentedControlContainerVariants,\n SegmentedControlSegmentVariants,\n} from './segmented-control.variants';\n","/**\n * Generated bundle index. Do not edit.\n */\n\nexport * from './index';\n"],"names":[],"mappings":"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"}
|
|
@@ -1,12 +1,12 @@
|
|
|
1
1
|
import { cva } from 'class-variance-authority';
|
|
2
2
|
import * as i0 from '@angular/core';
|
|
3
|
-
import { model, input, booleanAttribute, output, Directive, computed, ChangeDetectionStrategy, Component, inject, DestroyRef } from '@angular/core';
|
|
3
|
+
import { model, input, booleanAttribute, output, Directive, computed, ChangeDetectionStrategy, Component, inject, DestroyRef, ElementRef } from '@angular/core';
|
|
4
4
|
|
|
5
5
|
// ─── Sort Header Variants ───
|
|
6
6
|
/**
|
|
7
7
|
* @tokens `--color-foreground`, `--color-muted-foreground`
|
|
8
8
|
*/
|
|
9
|
-
const sortHeaderVariants = cva(['
|
|
9
|
+
const sortHeaderVariants = cva(['select-none', 'transition-colors duration-normal'], {
|
|
10
10
|
variants: {
|
|
11
11
|
sortable: {
|
|
12
12
|
true: 'cursor-pointer hover:text-foreground',
|
|
@@ -31,7 +31,7 @@ const sortHeaderVariants = cva(['inline-flex items-center gap-1.5', 'select-none
|
|
|
31
31
|
/**
|
|
32
32
|
* @tokens `--color-foreground`, `--color-muted-foreground`
|
|
33
33
|
*/
|
|
34
|
-
const sortIconVariants = cva(['inline-flex items-center justify-center', 'shrink-0', 'transition-all duration-
|
|
34
|
+
const sortIconVariants = cva(['inline-flex items-center justify-center', 'shrink-0', 'transition-all duration-slow ease-out'], {
|
|
35
35
|
variants: {
|
|
36
36
|
size: {
|
|
37
37
|
sm: 'size-3',
|
|
@@ -55,7 +55,7 @@ const DEFAULT_SORT_CYCLE = ['asc', 'desc', undefined];
|
|
|
55
55
|
/**
|
|
56
56
|
* Parent directive that manages sort state for a group of sortable headers.
|
|
57
57
|
*
|
|
58
|
-
* Apply to a container element (e.g., `<tr>`, `<div>`) that contains `[
|
|
58
|
+
* Apply to a container element (e.g., `<tr>`, `<div>`) that contains `[comSortHeader]` children.
|
|
59
59
|
* Children inject this directive via DI and read its signals directly.
|
|
60
60
|
*
|
|
61
61
|
* @tokens `--color-foreground`, `--color-muted-foreground`
|
|
@@ -75,7 +75,7 @@ const DEFAULT_SORT_CYCLE = ['asc', 'desc', undefined];
|
|
|
75
75
|
* </tr>
|
|
76
76
|
* ```
|
|
77
77
|
*/
|
|
78
|
-
class
|
|
78
|
+
class ComSort {
|
|
79
79
|
// ─── Inputs ───
|
|
80
80
|
/** Currently active sort column id — two-way via model() */
|
|
81
81
|
sortActive = model(undefined, ...(ngDevMode ? [{ debugName: "sortActive" }] : []));
|
|
@@ -137,27 +137,25 @@ class SortDirective {
|
|
|
137
137
|
const nextIndex = (currentIndex + 1) % cycle.length;
|
|
138
138
|
return cycle[nextIndex];
|
|
139
139
|
}
|
|
140
|
-
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.0", ngImport: i0, type:
|
|
141
|
-
static ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "17.1.0", version: "21.2.0", type:
|
|
140
|
+
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.0", ngImport: i0, type: ComSort, deps: [], target: i0.ɵɵFactoryTarget.Directive });
|
|
141
|
+
static ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "17.1.0", version: "21.2.0", type: ComSort, isStandalone: true, selector: "[comSort]", inputs: { sortActive: { classPropertyName: "sortActive", publicName: "sortActive", isSignal: true, isRequired: false, transformFunction: null }, sortDirection: { classPropertyName: "sortDirection", publicName: "sortDirection", isSignal: true, isRequired: false, transformFunction: null }, sortDisabled: { classPropertyName: "sortDisabled", publicName: "sortDisabled", isSignal: true, isRequired: false, transformFunction: null }, sortCycle: { classPropertyName: "sortCycle", publicName: "sortCycle", isSignal: true, isRequired: false, transformFunction: null }, sortShowIndicator: { classPropertyName: "sortShowIndicator", publicName: "sortShowIndicator", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { sortActive: "sortActiveChange", sortDirection: "sortDirectionChange", sortChange: "sortChange" }, exportAs: ["comSort"], ngImport: i0 });
|
|
142
142
|
}
|
|
143
|
-
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.0", ngImport: i0, type:
|
|
143
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.0", ngImport: i0, type: ComSort, decorators: [{
|
|
144
144
|
type: Directive,
|
|
145
145
|
args: [{
|
|
146
146
|
selector: '[comSort]',
|
|
147
147
|
exportAs: 'comSort',
|
|
148
|
-
host: {
|
|
149
|
-
class: 'contents',
|
|
150
|
-
},
|
|
148
|
+
host: {},
|
|
151
149
|
}]
|
|
152
150
|
}], propDecorators: { sortActive: [{ type: i0.Input, args: [{ isSignal: true, alias: "sortActive", required: false }] }, { type: i0.Output, args: ["sortActiveChange"] }], sortDirection: [{ type: i0.Input, args: [{ isSignal: true, alias: "sortDirection", required: false }] }, { type: i0.Output, args: ["sortDirectionChange"] }], sortDisabled: [{ type: i0.Input, args: [{ isSignal: true, alias: "sortDisabled", required: false }] }], sortCycle: [{ type: i0.Input, args: [{ isSignal: true, alias: "sortCycle", required: false }] }], sortShowIndicator: [{ type: i0.Input, args: [{ isSignal: true, alias: "sortShowIndicator", required: false }] }], sortChange: [{ type: i0.Output, args: ["sortChange"] }] } });
|
|
153
151
|
|
|
154
152
|
/**
|
|
155
153
|
* Internal animated SVG arrow indicator for sort headers.
|
|
156
|
-
* Not exported — used only inside
|
|
154
|
+
* Not exported — used only inside ComSortHeader.
|
|
157
155
|
*
|
|
158
156
|
* @tokens `--color-foreground`, `--color-muted-foreground`
|
|
159
157
|
*/
|
|
160
|
-
class
|
|
158
|
+
class ComSortIcon {
|
|
161
159
|
/** Current sort direction */
|
|
162
160
|
direction = input(undefined, ...(ngDevMode ? [{ debugName: "direction" }] : []));
|
|
163
161
|
/** Whether the column is actively sorted */
|
|
@@ -179,8 +177,8 @@ class SortIconComponent {
|
|
|
179
177
|
size: 'md',
|
|
180
178
|
state: this.iconState(),
|
|
181
179
|
}), ...(ngDevMode ? [{ debugName: "iconClasses" }] : []));
|
|
182
|
-
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.0", ngImport: i0, type:
|
|
183
|
-
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.1.0", version: "21.2.0", type:
|
|
180
|
+
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.0", ngImport: i0, type: ComSortIcon, deps: [], target: i0.ɵɵFactoryTarget.Component });
|
|
181
|
+
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.1.0", version: "21.2.0", type: ComSortIcon, isStandalone: true, selector: "com-sort-icon", inputs: { direction: { classPropertyName: "direction", publicName: "direction", isSignal: true, isRequired: false, transformFunction: null }, isSorted: { classPropertyName: "isSorted", publicName: "isSorted", isSignal: true, isRequired: false, transformFunction: null }, showWhenUnsorted: { classPropertyName: "showWhenUnsorted", publicName: "showWhenUnsorted", isSignal: true, isRequired: false, transformFunction: null } }, ngImport: i0, template: `
|
|
184
182
|
<span [class]="iconClasses()">
|
|
185
183
|
<svg
|
|
186
184
|
xmlns="http://www.w3.org/2000/svg"
|
|
@@ -199,7 +197,7 @@ class SortIconComponent {
|
|
|
199
197
|
</span>
|
|
200
198
|
`, isInline: true, changeDetection: i0.ChangeDetectionStrategy.OnPush });
|
|
201
199
|
}
|
|
202
|
-
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.0", ngImport: i0, type:
|
|
200
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.0", ngImport: i0, type: ComSortIcon, decorators: [{
|
|
203
201
|
type: Component,
|
|
204
202
|
args: [{
|
|
205
203
|
selector: 'com-sort-icon',
|
|
@@ -226,7 +224,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.0", ngImpor
|
|
|
226
224
|
}], propDecorators: { direction: [{ type: i0.Input, args: [{ isSignal: true, alias: "direction", required: false }] }], isSorted: [{ type: i0.Input, args: [{ isSignal: true, alias: "isSorted", required: false }] }], showWhenUnsorted: [{ type: i0.Input, args: [{ isSignal: true, alias: "showWhenUnsorted", required: false }] }] } });
|
|
227
225
|
|
|
228
226
|
/**
|
|
229
|
-
* Sortable header component — child of [
|
|
227
|
+
* Sortable header component — child of [comSort] directive.
|
|
230
228
|
*
|
|
231
229
|
* Apply to table headers, div columns, or any clickable element that should trigger sorting.
|
|
232
230
|
*
|
|
@@ -245,9 +243,10 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.0", ngImpor
|
|
|
245
243
|
* <th comSortHeader="name" comSortHeaderArrowPosition="before">Name</th>
|
|
246
244
|
* ```
|
|
247
245
|
*/
|
|
248
|
-
class
|
|
249
|
-
sort = inject(
|
|
246
|
+
class ComSortHeader {
|
|
247
|
+
sort = inject(ComSort, { optional: true });
|
|
250
248
|
destroyRef = inject(DestroyRef);
|
|
249
|
+
elementRef = inject(ElementRef);
|
|
251
250
|
// ─── Inputs ───
|
|
252
251
|
/** The column id — aliased from the selector */
|
|
253
252
|
id = input.required({ ...(ngDevMode ? { debugName: "id" } : {}), alias: 'comSortHeader' });
|
|
@@ -268,6 +267,8 @@ class SortHeaderComponent {
|
|
|
268
267
|
showUnsortedIndicator = computed(() => this.sortHeaderShowIndicator() ?? this.sort?.sortShowIndicator() ?? false, ...(ngDevMode ? [{ debugName: "showUnsortedIndicator" }] : []));
|
|
269
268
|
/** Whether sorting is disabled for this header */
|
|
270
269
|
isDisabled = computed(() => this.sortHeaderDisabled() || this.sort?.sortDisabled() || false, ...(ngDevMode ? [{ debugName: "isDisabled" }] : []));
|
|
270
|
+
/** Role — only set on non-<th> elements (th has implicit columnheader role) */
|
|
271
|
+
hostRole = computed(() => this.elementRef.nativeElement.tagName === 'TH' ? null : 'columnheader', ...(ngDevMode ? [{ debugName: "hostRole" }] : []));
|
|
271
272
|
/** aria-sort attribute value */
|
|
272
273
|
ariaSort = computed(() => {
|
|
273
274
|
if (!this.isSorted())
|
|
@@ -297,56 +298,61 @@ class SortHeaderComponent {
|
|
|
297
298
|
return;
|
|
298
299
|
this.sort.sort(this.id());
|
|
299
300
|
}
|
|
300
|
-
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.0", ngImport: i0, type:
|
|
301
|
-
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.0", type:
|
|
302
|
-
|
|
303
|
-
|
|
304
|
-
|
|
305
|
-
|
|
306
|
-
|
|
307
|
-
|
|
308
|
-
|
|
301
|
+
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.0", ngImport: i0, type: ComSortHeader, deps: [], target: i0.ɵɵFactoryTarget.Component });
|
|
302
|
+
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.0", type: ComSortHeader, isStandalone: true, selector: "[comSortHeader]", inputs: { id: { classPropertyName: "id", publicName: "comSortHeader", isSignal: true, isRequired: true, transformFunction: null }, sortHeaderDisabled: { classPropertyName: "sortHeaderDisabled", publicName: "sortHeaderDisabled", isSignal: true, isRequired: false, transformFunction: null }, sortHeaderShowIndicator: { classPropertyName: "sortHeaderShowIndicator", publicName: "sortHeaderShowIndicator", isSignal: true, isRequired: false, transformFunction: null }, sortHeaderArrowPosition: { classPropertyName: "sortHeaderArrowPosition", publicName: "comSortHeaderArrowPosition", isSignal: true, isRequired: false, transformFunction: null } }, host: { listeners: { "click": "onClick()", "keydown.enter": "onClick()", "keydown.space": "$event.preventDefault(); onClick()" }, properties: { "class": "hostClasses()", "attr.aria-sort": "ariaSort()", "attr.role": "hostRole()", "attr.tabindex": "isDisabled() ? -1 : 0", "attr.aria-disabled": "isDisabled() || null" } }, ngImport: i0, template: `
|
|
303
|
+
<span class="inline-flex items-center gap-1.5">
|
|
304
|
+
@if (sortHeaderArrowPosition() === 'before') {
|
|
305
|
+
<com-sort-icon
|
|
306
|
+
[direction]="direction()"
|
|
307
|
+
[isSorted]="isSorted()"
|
|
308
|
+
[showWhenUnsorted]="showUnsortedIndicator()"
|
|
309
|
+
/>
|
|
310
|
+
}
|
|
309
311
|
|
|
310
|
-
|
|
312
|
+
<ng-content />
|
|
311
313
|
|
|
312
|
-
|
|
313
|
-
|
|
314
|
-
|
|
315
|
-
|
|
316
|
-
|
|
317
|
-
|
|
318
|
-
|
|
319
|
-
|
|
314
|
+
@if (sortHeaderArrowPosition() === 'after') {
|
|
315
|
+
<com-sort-icon
|
|
316
|
+
[direction]="direction()"
|
|
317
|
+
[isSorted]="isSorted()"
|
|
318
|
+
[showWhenUnsorted]="showUnsortedIndicator()"
|
|
319
|
+
/>
|
|
320
|
+
}
|
|
321
|
+
</span>
|
|
322
|
+
`, isInline: true, dependencies: [{ kind: "component", type: ComSortIcon, selector: "com-sort-icon", inputs: ["direction", "isSorted", "showWhenUnsorted"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
|
|
320
323
|
}
|
|
321
|
-
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.0", ngImport: i0, type:
|
|
324
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.0", ngImport: i0, type: ComSortHeader, decorators: [{
|
|
322
325
|
type: Component,
|
|
323
326
|
args: [{
|
|
327
|
+
// eslint-disable-next-line @angular-eslint/component-selector -- attribute selector used on <th> host elements
|
|
324
328
|
selector: '[comSortHeader]',
|
|
325
329
|
template: `
|
|
326
|
-
|
|
327
|
-
|
|
328
|
-
|
|
329
|
-
|
|
330
|
-
|
|
331
|
-
|
|
332
|
-
|
|
330
|
+
<span class="inline-flex items-center gap-1.5">
|
|
331
|
+
@if (sortHeaderArrowPosition() === 'before') {
|
|
332
|
+
<com-sort-icon
|
|
333
|
+
[direction]="direction()"
|
|
334
|
+
[isSorted]="isSorted()"
|
|
335
|
+
[showWhenUnsorted]="showUnsortedIndicator()"
|
|
336
|
+
/>
|
|
337
|
+
}
|
|
333
338
|
|
|
334
|
-
|
|
339
|
+
<ng-content />
|
|
335
340
|
|
|
336
|
-
|
|
337
|
-
|
|
338
|
-
|
|
339
|
-
|
|
340
|
-
|
|
341
|
-
|
|
342
|
-
|
|
341
|
+
@if (sortHeaderArrowPosition() === 'after') {
|
|
342
|
+
<com-sort-icon
|
|
343
|
+
[direction]="direction()"
|
|
344
|
+
[isSorted]="isSorted()"
|
|
345
|
+
[showWhenUnsorted]="showUnsortedIndicator()"
|
|
346
|
+
/>
|
|
347
|
+
}
|
|
348
|
+
</span>
|
|
343
349
|
`,
|
|
344
|
-
imports: [
|
|
350
|
+
imports: [ComSortIcon],
|
|
345
351
|
changeDetection: ChangeDetectionStrategy.OnPush,
|
|
346
352
|
host: {
|
|
347
353
|
'[class]': 'hostClasses()',
|
|
348
354
|
'[attr.aria-sort]': 'ariaSort()',
|
|
349
|
-
'[attr.role]': '
|
|
355
|
+
'[attr.role]': 'hostRole()',
|
|
350
356
|
'[attr.tabindex]': 'isDisabled() ? -1 : 0',
|
|
351
357
|
'[attr.aria-disabled]': 'isDisabled() || null',
|
|
352
358
|
'(click)': 'onClick()',
|
|
@@ -358,11 +364,11 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.0", ngImpor
|
|
|
358
364
|
|
|
359
365
|
// Public API for the sort component
|
|
360
366
|
// Types & Variants
|
|
361
|
-
// NOT exported:
|
|
367
|
+
// NOT exported: ComSortIcon (internal)
|
|
362
368
|
|
|
363
369
|
/**
|
|
364
370
|
* Generated bundle index. Do not edit.
|
|
365
371
|
*/
|
|
366
372
|
|
|
367
|
-
export {
|
|
373
|
+
export { ComSort, ComSortHeader, sortHeaderVariants, sortIconVariants };
|
|
368
374
|
//# sourceMappingURL=ngx-com-components-sort.mjs.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"ngx-com-components-sort.mjs","sources":["../../../projects/com/components/sort/sort.variants.ts","../../../projects/com/components/sort/sort.directive.ts","../../../projects/com/components/sort/sort-icon.component.ts","../../../projects/com/components/sort/sort-header.component.ts","../../../projects/com/components/sort/index.ts","../../../projects/com/components/sort/ngx-com-components-sort.ts"],"sourcesContent":["import { cva } from 'class-variance-authority';\n\n// ─── Type Exports ───\n\n/** Sort direction — three states */\nexport type SortDirection = 'asc' | 'desc' | undefined;\n\n/** Configures the three-state sort cycle */\nexport type SortCycle = SortDirection[];\n\n/** Emitted when sort state changes */\nexport interface SortEvent {\n /** The active column id, or undefined if unsorted */\n active: string | undefined;\n /** The sort direction */\n direction: SortDirection;\n}\n\n// ─── Sort Header Variants ───\n\n/**\n * @tokens `--color-foreground`, `--color-muted-foreground`\n */\nexport const sortHeaderVariants: (props?: {\n sortable?: boolean;\n active?: boolean;\n disabled?: boolean;\n}) => string = cva(\n ['inline-flex items-center gap-1.5', 'select-none', 'transition-colors duration-150'],\n {\n variants: {\n sortable: {\n true: 'cursor-pointer hover:text-foreground',\n false: 'cursor-default',\n },\n active: {\n true: 'text-foreground',\n false: 'text-muted-foreground',\n },\n disabled: {\n true: 'text-disabled-foreground cursor-not-allowed pointer-events-none',\n false: '',\n },\n },\n defaultVariants: {\n sortable: true,\n active: false,\n disabled: false,\n },\n }\n);\n\n// ─── Sort Icon Variants ───\n\n/**\n * @tokens `--color-foreground`, `--color-muted-foreground`\n */\nexport const sortIconVariants: (props?: {\n size?: 'sm' | 'md' | 'lg';\n state?: 'asc' | 'desc' | 'unsorted' | 'hidden';\n}) => string = cva(\n ['inline-flex items-center justify-center', 'shrink-0', 'transition-all duration-200 ease-out'],\n {\n variants: {\n size: {\n sm: 'size-3',\n md: 'size-3.5',\n lg: 'size-4',\n },\n state: {\n asc: 'text-foreground rotate-0',\n desc: 'text-foreground rotate-180',\n unsorted: 'text-muted-foreground rotate-0',\n hidden: 'invisible scale-75',\n },\n },\n defaultVariants: {\n size: 'md',\n state: 'hidden',\n },\n }\n);\n","import { booleanAttribute, Directive, input, model, output } from '@angular/core';\nimport type {\n InputSignal,\n InputSignalWithTransform,\n ModelSignal,\n OutputEmitterRef,\n} from '@angular/core';\nimport type { SortDirection, SortCycle, SortEvent } from './sort.variants';\nimport type { SortHeaderComponent } from './sort-header.component';\n\nconst DEFAULT_SORT_CYCLE: SortCycle = ['asc', 'desc', undefined];\n\n/**\n * Parent directive that manages sort state for a group of sortable headers.\n *\n * Apply to a container element (e.g., `<tr>`, `<div>`) that contains `[uiSortHeader]` children.\n * Children inject this directive via DI and read its signals directly.\n *\n * @tokens `--color-foreground`, `--color-muted-foreground`\n *\n * @example Basic usage\n * ```html\n * <tr comSort (sortChange)=\"onSort($event)\">\n * <th comSortHeader=\"name\">Name</th>\n * <th comSortHeader=\"age\">Age</th>\n * </tr>\n * ```\n *\n * @example Two-way binding\n * ```html\n * <tr comSort [(sortActive)]=\"column\" [(sortDirection)]=\"direction\">\n * <th comSortHeader=\"name\">Name</th>\n * </tr>\n * ```\n */\n@Directive({\n selector: '[comSort]',\n exportAs: 'comSort',\n host: {\n class: 'contents',\n },\n})\nexport class SortDirective {\n // ─── Inputs ───\n\n /** Currently active sort column id — two-way via model() */\n readonly sortActive: ModelSignal<string | undefined> = model<string | undefined>(undefined);\n\n /** Current sort direction — two-way via model() */\n readonly sortDirection: ModelSignal<SortDirection> = model<SortDirection>(undefined);\n\n /** Disables all sorting in this container */\n readonly sortDisabled: InputSignalWithTransform<boolean, unknown> = input(false, {\n transform: booleanAttribute,\n });\n\n /** Customize the click cycle (e.g., ['asc', 'desc'] to skip unsorted) */\n readonly sortCycle: InputSignal<SortCycle> = input<SortCycle>(DEFAULT_SORT_CYCLE);\n\n /** Show a muted arrow on unsorted headers */\n readonly sortShowIndicator: InputSignalWithTransform<boolean, unknown> = input(false, {\n transform: booleanAttribute,\n });\n\n // ─── Outputs ───\n\n /** Emitted when active column or direction changes */\n readonly sortChange: OutputEmitterRef<SortEvent> = output<SortEvent>();\n\n // ─── Registration ───\n\n private readonly headers: Map<string, SortHeaderComponent> = new Map<string, SortHeaderComponent>();\n\n /** Register a sort header with this parent */\n register(header: SortHeaderComponent): void {\n this.headers.set(header.id(), header);\n }\n\n /** Deregister a sort header */\n deregister(id: string): void {\n this.headers.delete(id);\n }\n\n // ─── Public API ───\n\n /** Programmatically sort by a column */\n sort(id: string): void {\n if (this.sortDisabled()) return;\n\n const cycle = this.sortCycle();\n\n if (this.sortActive() !== id) {\n // New column — start at first direction in cycle\n this.sortActive.set(id);\n this.sortDirection.set(cycle[0]);\n } else {\n // Same column — advance cycle\n const currentIndex = cycle.indexOf(this.sortDirection());\n const nextIndex = (currentIndex + 1) % cycle.length;\n const nextDir = cycle[nextIndex];\n this.sortDirection.set(nextDir);\n\n // If direction is undefined, clear active\n if (nextDir === undefined) {\n this.sortActive.set(undefined);\n }\n }\n\n this.sortChange.emit({\n active: this.sortActive(),\n direction: this.sortDirection(),\n });\n }\n\n /** Returns the next direction in the cycle for a given column */\n getNextDirection(id: string): SortDirection {\n const cycle = this.sortCycle();\n\n if (this.sortActive() !== id) {\n return cycle[0];\n }\n\n const currentIndex = cycle.indexOf(this.sortDirection());\n const nextIndex = (currentIndex + 1) % cycle.length;\n return cycle[nextIndex];\n }\n}\n","import { ChangeDetectionStrategy, Component, computed, input } from '@angular/core';\nimport type { InputSignal, Signal } from '@angular/core';\nimport { sortIconVariants } from './sort.variants';\nimport type { SortDirection } from './sort.variants';\n\n/**\n * Internal animated SVG arrow indicator for sort headers.\n * Not exported — used only inside SortHeaderComponent.\n *\n * @tokens `--color-foreground`, `--color-muted-foreground`\n */\n@Component({\n selector: 'com-sort-icon',\n template: `\n <span [class]=\"iconClasses()\">\n <svg\n xmlns=\"http://www.w3.org/2000/svg\"\n viewBox=\"0 0 24 24\"\n fill=\"none\"\n stroke=\"currentColor\"\n stroke-width=\"2.5\"\n stroke-linecap=\"round\"\n stroke-linejoin=\"round\"\n class=\"size-full\"\n aria-hidden=\"true\"\n >\n <path d=\"M12 19V5\" />\n <path d=\"M5 12l7-7 7 7\" />\n </svg>\n </span>\n `,\n changeDetection: ChangeDetectionStrategy.OnPush,\n})\nexport class SortIconComponent {\n /** Current sort direction */\n readonly direction: InputSignal<SortDirection> = input<SortDirection>(undefined);\n\n /** Whether the column is actively sorted */\n readonly isSorted: InputSignal<boolean> = input(false);\n\n /** Show a muted indicator when not sorted */\n readonly showWhenUnsorted: InputSignal<boolean> = input(false);\n\n /** Compute the icon state for CVA */\n private readonly iconState: Signal<'asc' | 'desc' | 'unsorted' | 'hidden'> = computed(() => {\n if (this.isSorted()) {\n return this.direction() === 'asc' ? 'asc' : 'desc';\n }\n if (this.showWhenUnsorted()) {\n return 'unsorted';\n }\n return 'hidden';\n });\n\n /** CVA-generated classes for the icon container */\n readonly iconClasses: Signal<string> = computed(() =>\n sortIconVariants({\n size: 'md',\n state: this.iconState(),\n })\n );\n}\n","import {\n booleanAttribute,\n ChangeDetectionStrategy,\n Component,\n computed,\n DestroyRef,\n inject,\n input,\n} from '@angular/core';\nimport type {\n InputSignal,\n InputSignalWithTransform,\n OnInit,\n Signal,\n} from '@angular/core';\nimport { SortDirective } from './sort.directive';\nimport { SortIconComponent } from './sort-icon.component';\nimport { sortHeaderVariants } from './sort.variants';\nimport type { SortDirection } from './sort.variants';\n\n/**\n * Sortable header component — child of [uiSort] directive.\n *\n * Apply to table headers, div columns, or any clickable element that should trigger sorting.\n *\n * @tokens `--color-foreground`, `--color-muted-foreground`, `--color-disabled-foreground`\n *\n * @example Basic usage\n * ```html\n * <tr comSort (sortChange)=\"onSort($event)\">\n * <th comSortHeader=\"name\">Name</th>\n * <th comSortHeader=\"age\">Age</th>\n * </tr>\n * ```\n *\n * @example Arrow placement\n * ```html\n * <th comSortHeader=\"name\" comSortHeaderArrowPosition=\"before\">Name</th>\n * ```\n */\n@Component({\n selector: '[comSortHeader]',\n template: `\n @if (sortHeaderArrowPosition() === 'before') {\n <com-sort-icon\n [direction]=\"direction()\"\n [isSorted]=\"isSorted()\"\n [showWhenUnsorted]=\"showUnsortedIndicator()\"\n />\n }\n\n <ng-content />\n\n @if (sortHeaderArrowPosition() === 'after') {\n <com-sort-icon\n [direction]=\"direction()\"\n [isSorted]=\"isSorted()\"\n [showWhenUnsorted]=\"showUnsortedIndicator()\"\n />\n }\n `,\n imports: [SortIconComponent],\n changeDetection: ChangeDetectionStrategy.OnPush,\n host: {\n '[class]': 'hostClasses()',\n '[attr.aria-sort]': 'ariaSort()',\n '[attr.role]': '\"columnheader\"',\n '[attr.tabindex]': 'isDisabled() ? -1 : 0',\n '[attr.aria-disabled]': 'isDisabled() || null',\n '(click)': 'onClick()',\n '(keydown.enter)': 'onClick()',\n '(keydown.space)': '$event.preventDefault(); onClick()',\n },\n})\nexport class SortHeaderComponent implements OnInit {\n private readonly sort: SortDirective | null = inject(SortDirective, { optional: true });\n private readonly destroyRef: DestroyRef = inject(DestroyRef);\n\n // ─── Inputs ───\n\n /** The column id — aliased from the selector */\n readonly id: InputSignal<string> = input.required<string>({ alias: 'comSortHeader' });\n\n /** Disable sorting for this specific header */\n readonly sortHeaderDisabled: InputSignalWithTransform<boolean, unknown> = input(false, {\n transform: booleanAttribute,\n });\n\n /** Override parent's sortShowIndicator for this header */\n readonly sortHeaderShowIndicator: InputSignal<boolean | undefined> = input<boolean | undefined>(\n undefined\n );\n\n /** Arrow placement relative to content */\n readonly sortHeaderArrowPosition: InputSignal<'before' | 'after'> = input<'before' | 'after'>(\n 'after',\n { alias: 'comSortHeaderArrowPosition' }\n );\n\n // ─── Computed State (from parent signals) ───\n\n /** Whether this header is the currently active sort column */\n readonly isActive: Signal<boolean> = computed(() => this.sort?.sortActive() === this.id());\n\n /** Current direction if active, undefined otherwise */\n readonly direction: Signal<SortDirection> = computed(() =>\n this.isActive() ? this.sort?.sortDirection() : undefined\n );\n\n /** Whether this header is sorted (active + has direction) */\n readonly isSorted: Signal<boolean> = computed(\n () => this.isActive() && this.sort?.sortDirection() !== undefined\n );\n\n /** Whether to show the muted indicator when unsorted */\n readonly showUnsortedIndicator: Signal<boolean> = computed(\n () => this.sortHeaderShowIndicator() ?? this.sort?.sortShowIndicator() ?? false\n );\n\n /** Whether sorting is disabled for this header */\n readonly isDisabled: Signal<boolean> = computed(\n () => this.sortHeaderDisabled() || this.sort?.sortDisabled() || false\n );\n\n /** aria-sort attribute value */\n readonly ariaSort: Signal<'ascending' | 'descending' | 'none'> = computed(() => {\n if (!this.isSorted()) return 'none';\n return this.direction() === 'asc' ? 'ascending' : 'descending';\n });\n\n /** CVA-generated host classes */\n readonly hostClasses: Signal<string> = computed(() =>\n sortHeaderVariants({\n sortable: !this.isDisabled(),\n active: this.isSorted(),\n disabled: this.isDisabled(),\n })\n );\n\n constructor() {\n if (!this.sort) {\n throw new Error('comSortHeader must be placed inside a [comSort] container.');\n }\n\n this.destroyRef.onDestroy(() => {\n this.sort?.deregister(this.id());\n });\n }\n\n ngOnInit(): void {\n this.sort!.register(this);\n }\n\n // ─── Event Handlers ───\n\n protected onClick(): void {\n if (this.isDisabled()) return;\n this.sort!.sort(this.id());\n }\n}\n","// Public API for the sort component\n\n// Types & Variants\nexport {\n sortHeaderVariants,\n sortIconVariants,\n type SortDirection,\n type SortCycle,\n type SortEvent,\n} from './sort.variants';\n\n// Directives & Components\nexport { SortDirective } from './sort.directive';\nexport { SortHeaderComponent } from './sort-header.component';\n\n// NOT exported: SortIconComponent (internal)\n","/**\n * Generated bundle index. Do not edit.\n */\n\nexport * from './index';\n"],"names":[],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"ngx-com-components-sort.mjs","sources":["../../../projects/com/components/sort/sort.variants.ts","../../../projects/com/components/sort/sort.directive.ts","../../../projects/com/components/sort/sort-icon.component.ts","../../../projects/com/components/sort/sort-header.component.ts","../../../projects/com/components/sort/index.ts","../../../projects/com/components/sort/ngx-com-components-sort.ts"],"sourcesContent":["import { cva } from 'class-variance-authority';\n\n// ─── Type Exports ───\n\n/** Sort direction — three states */\nexport type SortDirection = 'asc' | 'desc' | undefined;\n\n/** Configures the three-state sort cycle */\nexport type SortCycle = SortDirection[];\n\n/** Emitted when sort state changes */\nexport interface SortEvent {\n /** The active column id, or undefined if unsorted */\n active: string | undefined;\n /** The sort direction */\n direction: SortDirection;\n}\n\n// ─── Sort Header Variants ───\n\n/**\n * @tokens `--color-foreground`, `--color-muted-foreground`\n */\nexport const sortHeaderVariants: (props?: {\n sortable?: boolean;\n active?: boolean;\n disabled?: boolean;\n}) => string = cva(\n ['select-none', 'transition-colors duration-normal'],\n {\n variants: {\n sortable: {\n true: 'cursor-pointer hover:text-foreground',\n false: 'cursor-default',\n },\n active: {\n true: 'text-foreground',\n false: 'text-muted-foreground',\n },\n disabled: {\n true: 'text-disabled-foreground cursor-not-allowed pointer-events-none',\n false: '',\n },\n },\n defaultVariants: {\n sortable: true,\n active: false,\n disabled: false,\n },\n }\n);\n\n// ─── Sort Icon Variants ───\n\n/**\n * @tokens `--color-foreground`, `--color-muted-foreground`\n */\nexport const sortIconVariants: (props?: {\n size?: 'sm' | 'md' | 'lg';\n state?: 'asc' | 'desc' | 'unsorted' | 'hidden';\n}) => string = cva(\n ['inline-flex items-center justify-center', 'shrink-0', 'transition-all duration-slow ease-out'],\n {\n variants: {\n size: {\n sm: 'size-3',\n md: 'size-3.5',\n lg: 'size-4',\n },\n state: {\n asc: 'text-foreground rotate-0',\n desc: 'text-foreground rotate-180',\n unsorted: 'text-muted-foreground rotate-0',\n hidden: 'invisible scale-75',\n },\n },\n defaultVariants: {\n size: 'md',\n state: 'hidden',\n },\n }\n);\n","import { booleanAttribute, Directive, input, model, output } from '@angular/core';\nimport type {\n InputSignal,\n InputSignalWithTransform,\n ModelSignal,\n OutputEmitterRef,\n} from '@angular/core';\nimport type { SortDirection, SortCycle, SortEvent } from './sort.variants';\nimport type { ComSortHeader } from './sort-header.component';\n\nconst DEFAULT_SORT_CYCLE: SortCycle = ['asc', 'desc', undefined];\n\n/**\n * Parent directive that manages sort state for a group of sortable headers.\n *\n * Apply to a container element (e.g., `<tr>`, `<div>`) that contains `[comSortHeader]` children.\n * Children inject this directive via DI and read its signals directly.\n *\n * @tokens `--color-foreground`, `--color-muted-foreground`\n *\n * @example Basic usage\n * ```html\n * <tr comSort (sortChange)=\"onSort($event)\">\n * <th comSortHeader=\"name\">Name</th>\n * <th comSortHeader=\"age\">Age</th>\n * </tr>\n * ```\n *\n * @example Two-way binding\n * ```html\n * <tr comSort [(sortActive)]=\"column\" [(sortDirection)]=\"direction\">\n * <th comSortHeader=\"name\">Name</th>\n * </tr>\n * ```\n */\n@Directive({\n selector: '[comSort]',\n exportAs: 'comSort',\n host: {},\n})\nexport class ComSort {\n // ─── Inputs ───\n\n /** Currently active sort column id — two-way via model() */\n readonly sortActive: ModelSignal<string | undefined> = model<string | undefined>(undefined);\n\n /** Current sort direction — two-way via model() */\n readonly sortDirection: ModelSignal<SortDirection> = model<SortDirection>(undefined);\n\n /** Disables all sorting in this container */\n readonly sortDisabled: InputSignalWithTransform<boolean, unknown> = input(false, {\n transform: booleanAttribute,\n });\n\n /** Customize the click cycle (e.g., ['asc', 'desc'] to skip unsorted) */\n readonly sortCycle: InputSignal<SortCycle> = input<SortCycle>(DEFAULT_SORT_CYCLE);\n\n /** Show a muted arrow on unsorted headers */\n readonly sortShowIndicator: InputSignalWithTransform<boolean, unknown> = input(false, {\n transform: booleanAttribute,\n });\n\n // ─── Outputs ───\n\n /** Emitted when active column or direction changes */\n readonly sortChange: OutputEmitterRef<SortEvent> = output<SortEvent>();\n\n // ─── Registration ───\n\n private readonly headers: Map<string, ComSortHeader> = new Map<string, ComSortHeader>();\n\n /** Register a sort header with this parent */\n register(header: ComSortHeader): void {\n this.headers.set(header.id(), header);\n }\n\n /** Deregister a sort header */\n deregister(id: string): void {\n this.headers.delete(id);\n }\n\n // ─── Public API ───\n\n /** Programmatically sort by a column */\n sort(id: string): void {\n if (this.sortDisabled()) return;\n\n const cycle = this.sortCycle();\n\n if (this.sortActive() !== id) {\n // New column — start at first direction in cycle\n this.sortActive.set(id);\n this.sortDirection.set(cycle[0]);\n } else {\n // Same column — advance cycle\n const currentIndex = cycle.indexOf(this.sortDirection());\n const nextIndex = (currentIndex + 1) % cycle.length;\n const nextDir = cycle[nextIndex];\n this.sortDirection.set(nextDir);\n\n // If direction is undefined, clear active\n if (nextDir === undefined) {\n this.sortActive.set(undefined);\n }\n }\n\n this.sortChange.emit({\n active: this.sortActive(),\n direction: this.sortDirection(),\n });\n }\n\n /** Returns the next direction in the cycle for a given column */\n getNextDirection(id: string): SortDirection {\n const cycle = this.sortCycle();\n\n if (this.sortActive() !== id) {\n return cycle[0];\n }\n\n const currentIndex = cycle.indexOf(this.sortDirection());\n const nextIndex = (currentIndex + 1) % cycle.length;\n return cycle[nextIndex];\n }\n}\n","import { ChangeDetectionStrategy, Component, computed, input } from '@angular/core';\nimport type { InputSignal, Signal } from '@angular/core';\nimport { sortIconVariants } from './sort.variants';\nimport type { SortDirection } from './sort.variants';\n\n/**\n * Internal animated SVG arrow indicator for sort headers.\n * Not exported — used only inside ComSortHeader.\n *\n * @tokens `--color-foreground`, `--color-muted-foreground`\n */\n@Component({\n selector: 'com-sort-icon',\n template: `\n <span [class]=\"iconClasses()\">\n <svg\n xmlns=\"http://www.w3.org/2000/svg\"\n viewBox=\"0 0 24 24\"\n fill=\"none\"\n stroke=\"currentColor\"\n stroke-width=\"2.5\"\n stroke-linecap=\"round\"\n stroke-linejoin=\"round\"\n class=\"size-full\"\n aria-hidden=\"true\"\n >\n <path d=\"M12 19V5\" />\n <path d=\"M5 12l7-7 7 7\" />\n </svg>\n </span>\n `,\n changeDetection: ChangeDetectionStrategy.OnPush,\n})\nexport class ComSortIcon {\n /** Current sort direction */\n readonly direction: InputSignal<SortDirection> = input<SortDirection>(undefined);\n\n /** Whether the column is actively sorted */\n readonly isSorted: InputSignal<boolean> = input(false);\n\n /** Show a muted indicator when not sorted */\n readonly showWhenUnsorted: InputSignal<boolean> = input(false);\n\n /** Compute the icon state for CVA */\n private readonly iconState: Signal<'asc' | 'desc' | 'unsorted' | 'hidden'> = computed(() => {\n if (this.isSorted()) {\n return this.direction() === 'asc' ? 'asc' : 'desc';\n }\n if (this.showWhenUnsorted()) {\n return 'unsorted';\n }\n return 'hidden';\n });\n\n /** CVA-generated classes for the icon container */\n readonly iconClasses: Signal<string> = computed(() =>\n sortIconVariants({\n size: 'md',\n state: this.iconState(),\n })\n );\n}\n","import {\n booleanAttribute,\n ChangeDetectionStrategy,\n Component,\n computed,\n DestroyRef,\n ElementRef,\n inject,\n input,\n} from '@angular/core';\nimport type {\n InputSignal,\n InputSignalWithTransform,\n OnInit,\n Signal,\n} from '@angular/core';\nimport { ComSort } from './sort.directive';\nimport { ComSortIcon } from './sort-icon.component';\nimport { sortHeaderVariants } from './sort.variants';\nimport type { SortDirection } from './sort.variants';\n\n/**\n * Sortable header component — child of [comSort] directive.\n *\n * Apply to table headers, div columns, or any clickable element that should trigger sorting.\n *\n * @tokens `--color-foreground`, `--color-muted-foreground`, `--color-disabled-foreground`\n *\n * @example Basic usage\n * ```html\n * <tr comSort (sortChange)=\"onSort($event)\">\n * <th comSortHeader=\"name\">Name</th>\n * <th comSortHeader=\"age\">Age</th>\n * </tr>\n * ```\n *\n * @example Arrow placement\n * ```html\n * <th comSortHeader=\"name\" comSortHeaderArrowPosition=\"before\">Name</th>\n * ```\n */\n@Component({\n // eslint-disable-next-line @angular-eslint/component-selector -- attribute selector used on <th> host elements\n selector: '[comSortHeader]',\n template: `\n <span class=\"inline-flex items-center gap-1.5\">\n @if (sortHeaderArrowPosition() === 'before') {\n <com-sort-icon\n [direction]=\"direction()\"\n [isSorted]=\"isSorted()\"\n [showWhenUnsorted]=\"showUnsortedIndicator()\"\n />\n }\n\n <ng-content />\n\n @if (sortHeaderArrowPosition() === 'after') {\n <com-sort-icon\n [direction]=\"direction()\"\n [isSorted]=\"isSorted()\"\n [showWhenUnsorted]=\"showUnsortedIndicator()\"\n />\n }\n </span>\n `,\n imports: [ComSortIcon],\n changeDetection: ChangeDetectionStrategy.OnPush,\n host: {\n '[class]': 'hostClasses()',\n '[attr.aria-sort]': 'ariaSort()',\n '[attr.role]': 'hostRole()',\n '[attr.tabindex]': 'isDisabled() ? -1 : 0',\n '[attr.aria-disabled]': 'isDisabled() || null',\n '(click)': 'onClick()',\n '(keydown.enter)': 'onClick()',\n '(keydown.space)': '$event.preventDefault(); onClick()',\n },\n})\nexport class ComSortHeader implements OnInit {\n private readonly sort: ComSort | null = inject(ComSort, { optional: true });\n private readonly destroyRef: DestroyRef = inject(DestroyRef);\n private readonly elementRef: ElementRef<HTMLElement> = inject(ElementRef);\n\n // ─── Inputs ───\n\n /** The column id — aliased from the selector */\n readonly id: InputSignal<string> = input.required<string>({ alias: 'comSortHeader' });\n\n /** Disable sorting for this specific header */\n readonly sortHeaderDisabled: InputSignalWithTransform<boolean, unknown> = input(false, {\n transform: booleanAttribute,\n });\n\n /** Override parent's sortShowIndicator for this header */\n readonly sortHeaderShowIndicator: InputSignal<boolean | undefined> = input<boolean | undefined>(\n undefined\n );\n\n /** Arrow placement relative to content */\n readonly sortHeaderArrowPosition: InputSignal<'before' | 'after'> = input<'before' | 'after'>(\n 'after',\n { alias: 'comSortHeaderArrowPosition' }\n );\n\n // ─── Computed State (from parent signals) ───\n\n /** Whether this header is the currently active sort column */\n readonly isActive: Signal<boolean> = computed(() => this.sort?.sortActive() === this.id());\n\n /** Current direction if active, undefined otherwise */\n readonly direction: Signal<SortDirection> = computed(() =>\n this.isActive() ? this.sort?.sortDirection() : undefined\n );\n\n /** Whether this header is sorted (active + has direction) */\n readonly isSorted: Signal<boolean> = computed(\n () => this.isActive() && this.sort?.sortDirection() !== undefined\n );\n\n /** Whether to show the muted indicator when unsorted */\n readonly showUnsortedIndicator: Signal<boolean> = computed(\n () => this.sortHeaderShowIndicator() ?? this.sort?.sortShowIndicator() ?? false\n );\n\n /** Whether sorting is disabled for this header */\n readonly isDisabled: Signal<boolean> = computed(\n () => this.sortHeaderDisabled() || this.sort?.sortDisabled() || false\n );\n\n /** Role — only set on non-<th> elements (th has implicit columnheader role) */\n readonly hostRole: Signal<'columnheader' | null> = computed(() =>\n this.elementRef.nativeElement.tagName === 'TH' ? null : 'columnheader'\n );\n\n /** aria-sort attribute value */\n readonly ariaSort: Signal<'ascending' | 'descending' | 'none'> = computed(() => {\n if (!this.isSorted()) return 'none';\n return this.direction() === 'asc' ? 'ascending' : 'descending';\n });\n\n /** CVA-generated host classes */\n readonly hostClasses: Signal<string> = computed(() =>\n sortHeaderVariants({\n sortable: !this.isDisabled(),\n active: this.isSorted(),\n disabled: this.isDisabled(),\n })\n );\n\n constructor() {\n if (!this.sort) {\n throw new Error('comSortHeader must be placed inside a [comSort] container.');\n }\n\n this.destroyRef.onDestroy(() => {\n this.sort?.deregister(this.id());\n });\n }\n\n ngOnInit(): void {\n this.sort!.register(this);\n }\n\n // ─── Event Handlers ───\n\n protected onClick(): void {\n if (this.isDisabled()) return;\n this.sort!.sort(this.id());\n }\n}\n","// Public API for the sort component\n\n// Types & Variants\nexport {\n sortHeaderVariants,\n sortIconVariants,\n type SortDirection,\n type SortCycle,\n type SortEvent,\n} from './sort.variants';\n\n// Directives & Components\nexport { ComSort } from './sort.directive';\nexport { ComSortHeader } from './sort-header.component';\n\n// NOT exported: ComSortIcon (internal)\n","/**\n * Generated bundle index. Do not edit.\n */\n\nexport * from './index';\n"],"names":[],"mappings":";;;;AAkBA;AAEA;;AAEG;AACI,MAAM,kBAAkB,GAIhB,GAAG,CAChB,CAAC,aAAa,EAAE,mCAAmC,CAAC,EACpD;AACE,IAAA,QAAQ,EAAE;AACR,QAAA,QAAQ,EAAE;AACR,YAAA,IAAI,EAAE,sCAAsC;AAC5C,YAAA,KAAK,EAAE,gBAAgB;AACxB,SAAA;AACD,QAAA,MAAM,EAAE;AACN,YAAA,IAAI,EAAE,iBAAiB;AACvB,YAAA,KAAK,EAAE,uBAAuB;AAC/B,SAAA;AACD,QAAA,QAAQ,EAAE;AACR,YAAA,IAAI,EAAE,iEAAiE;AACvE,YAAA,KAAK,EAAE,EAAE;AACV,SAAA;AACF,KAAA;AACD,IAAA,eAAe,EAAE;AACf,QAAA,QAAQ,EAAE,IAAI;AACd,QAAA,MAAM,EAAE,KAAK;AACb,QAAA,QAAQ,EAAE,KAAK;AAChB,KAAA;AACF,CAAA;AAGH;AAEA;;AAEG;AACI,MAAM,gBAAgB,GAGd,GAAG,CAChB,CAAC,yCAAyC,EAAE,UAAU,EAAE,uCAAuC,CAAC,EAChG;AACE,IAAA,QAAQ,EAAE;AACR,QAAA,IAAI,EAAE;AACJ,YAAA,EAAE,EAAE,QAAQ;AACZ,YAAA,EAAE,EAAE,UAAU;AACd,YAAA,EAAE,EAAE,QAAQ;AACb,SAAA;AACD,QAAA,KAAK,EAAE;AACL,YAAA,GAAG,EAAE,0BAA0B;AAC/B,YAAA,IAAI,EAAE,4BAA4B;AAClC,YAAA,QAAQ,EAAE,gCAAgC;AAC1C,YAAA,MAAM,EAAE,oBAAoB;AAC7B,SAAA;AACF,KAAA;AACD,IAAA,eAAe,EAAE;AACf,QAAA,IAAI,EAAE,IAAI;AACV,QAAA,KAAK,EAAE,QAAQ;AAChB,KAAA;AACF,CAAA;;ACtEH,MAAM,kBAAkB,GAAc,CAAC,KAAK,EAAE,MAAM,EAAE,SAAS,CAAC;AAEhE;;;;;;;;;;;;;;;;;;;;;;AAsBG;MAMU,OAAO,CAAA;;;AAIT,IAAA,UAAU,GAAoC,KAAK,CAAqB,SAAS,sDAAC;;AAGlF,IAAA,aAAa,GAA+B,KAAK,CAAgB,SAAS,yDAAC;;IAG3E,YAAY,GAA+C,KAAK,CAAC,KAAK,yDAC7E,SAAS,EAAE,gBAAgB,EAAA,CAC3B;;AAGO,IAAA,SAAS,GAA2B,KAAK,CAAY,kBAAkB,qDAAC;;IAGxE,iBAAiB,GAA+C,KAAK,CAAC,KAAK,8DAClF,SAAS,EAAE,gBAAgB,EAAA,CAC3B;;;IAKO,UAAU,GAAgC,MAAM,EAAa;;AAIrD,IAAA,OAAO,GAA+B,IAAI,GAAG,EAAyB;;AAGvF,IAAA,QAAQ,CAAC,MAAqB,EAAA;AAC5B,QAAA,IAAI,CAAC,OAAO,CAAC,GAAG,CAAC,MAAM,CAAC,EAAE,EAAE,EAAE,MAAM,CAAC;IACvC;;AAGA,IAAA,UAAU,CAAC,EAAU,EAAA;AACnB,QAAA,IAAI,CAAC,OAAO,CAAC,MAAM,CAAC,EAAE,CAAC;IACzB;;;AAKA,IAAA,IAAI,CAAC,EAAU,EAAA;QACb,IAAI,IAAI,CAAC,YAAY,EAAE;YAAE;AAEzB,QAAA,MAAM,KAAK,GAAG,IAAI,CAAC,SAAS,EAAE;AAE9B,QAAA,IAAI,IAAI,CAAC,UAAU,EAAE,KAAK,EAAE,EAAE;;AAE5B,YAAA,IAAI,CAAC,UAAU,CAAC,GAAG,CAAC,EAAE,CAAC;YACvB,IAAI,CAAC,aAAa,CAAC,GAAG,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC;QAClC;aAAO;;YAEL,MAAM,YAAY,GAAG,KAAK,CAAC,OAAO,CAAC,IAAI,CAAC,aAAa,EAAE,CAAC;YACxD,MAAM,SAAS,GAAG,CAAC,YAAY,GAAG,CAAC,IAAI,KAAK,CAAC,MAAM;AACnD,YAAA,MAAM,OAAO,GAAG,KAAK,CAAC,SAAS,CAAC;AAChC,YAAA,IAAI,CAAC,aAAa,CAAC,GAAG,CAAC,OAAO,CAAC;;AAG/B,YAAA,IAAI,OAAO,KAAK,SAAS,EAAE;AACzB,gBAAA,IAAI,CAAC,UAAU,CAAC,GAAG,CAAC,SAAS,CAAC;YAChC;QACF;AAEA,QAAA,IAAI,CAAC,UAAU,CAAC,IAAI,CAAC;AACnB,YAAA,MAAM,EAAE,IAAI,CAAC,UAAU,EAAE;AACzB,YAAA,SAAS,EAAE,IAAI,CAAC,aAAa,EAAE;AAChC,SAAA,CAAC;IACJ;;AAGA,IAAA,gBAAgB,CAAC,EAAU,EAAA;AACzB,QAAA,MAAM,KAAK,GAAG,IAAI,CAAC,SAAS,EAAE;AAE9B,QAAA,IAAI,IAAI,CAAC,UAAU,EAAE,KAAK,EAAE,EAAE;AAC5B,YAAA,OAAO,KAAK,CAAC,CAAC,CAAC;QACjB;QAEA,MAAM,YAAY,GAAG,KAAK,CAAC,OAAO,CAAC,IAAI,CAAC,aAAa,EAAE,CAAC;QACxD,MAAM,SAAS,GAAG,CAAC,YAAY,GAAG,CAAC,IAAI,KAAK,CAAC,MAAM;AACnD,QAAA,OAAO,KAAK,CAAC,SAAS,CAAC;IACzB;uGAnFW,OAAO,EAAA,IAAA,EAAA,EAAA,EAAA,MAAA,EAAA,EAAA,CAAA,eAAA,CAAA,SAAA,EAAA,CAAA;2FAAP,OAAO,EAAA,YAAA,EAAA,IAAA,EAAA,QAAA,EAAA,WAAA,EAAA,MAAA,EAAA,EAAA,UAAA,EAAA,EAAA,iBAAA,EAAA,YAAA,EAAA,UAAA,EAAA,YAAA,EAAA,QAAA,EAAA,IAAA,EAAA,UAAA,EAAA,KAAA,EAAA,iBAAA,EAAA,IAAA,EAAA,EAAA,aAAA,EAAA,EAAA,iBAAA,EAAA,eAAA,EAAA,UAAA,EAAA,eAAA,EAAA,QAAA,EAAA,IAAA,EAAA,UAAA,EAAA,KAAA,EAAA,iBAAA,EAAA,IAAA,EAAA,EAAA,YAAA,EAAA,EAAA,iBAAA,EAAA,cAAA,EAAA,UAAA,EAAA,cAAA,EAAA,QAAA,EAAA,IAAA,EAAA,UAAA,EAAA,KAAA,EAAA,iBAAA,EAAA,IAAA,EAAA,EAAA,SAAA,EAAA,EAAA,iBAAA,EAAA,WAAA,EAAA,UAAA,EAAA,WAAA,EAAA,QAAA,EAAA,IAAA,EAAA,UAAA,EAAA,KAAA,EAAA,iBAAA,EAAA,IAAA,EAAA,EAAA,iBAAA,EAAA,EAAA,iBAAA,EAAA,mBAAA,EAAA,UAAA,EAAA,mBAAA,EAAA,QAAA,EAAA,IAAA,EAAA,UAAA,EAAA,KAAA,EAAA,iBAAA,EAAA,IAAA,EAAA,EAAA,EAAA,OAAA,EAAA,EAAA,UAAA,EAAA,kBAAA,EAAA,aAAA,EAAA,qBAAA,EAAA,UAAA,EAAA,YAAA,EAAA,EAAA,QAAA,EAAA,CAAA,SAAA,CAAA,EAAA,QAAA,EAAA,EAAA,EAAA,CAAA;;2FAAP,OAAO,EAAA,UAAA,EAAA,CAAA;kBALnB,SAAS;AAAC,YAAA,IAAA,EAAA,CAAA;AACT,oBAAA,QAAQ,EAAE,WAAW;AACrB,oBAAA,QAAQ,EAAE,SAAS;AACnB,oBAAA,IAAI,EAAE,EAAE;AACT,iBAAA;;;AClCD;;;;;AAKG;MAuBU,WAAW,CAAA;;AAEb,IAAA,SAAS,GAA+B,KAAK,CAAgB,SAAS,qDAAC;;AAGvE,IAAA,QAAQ,GAAyB,KAAK,CAAC,KAAK,oDAAC;;AAG7C,IAAA,gBAAgB,GAAyB,KAAK,CAAC,KAAK,4DAAC;;AAG7C,IAAA,SAAS,GAAmD,QAAQ,CAAC,MAAK;AACzF,QAAA,IAAI,IAAI,CAAC,QAAQ,EAAE,EAAE;AACnB,YAAA,OAAO,IAAI,CAAC,SAAS,EAAE,KAAK,KAAK,GAAG,KAAK,GAAG,MAAM;QACpD;AACA,QAAA,IAAI,IAAI,CAAC,gBAAgB,EAAE,EAAE;AAC3B,YAAA,OAAO,UAAU;QACnB;AACA,QAAA,OAAO,QAAQ;AACjB,IAAA,CAAC,qDAAC;;AAGO,IAAA,WAAW,GAAmB,QAAQ,CAAC,MAC9C,gBAAgB,CAAC;AACf,QAAA,IAAI,EAAE,IAAI;AACV,QAAA,KAAK,EAAE,IAAI,CAAC,SAAS,EAAE;AACxB,KAAA,CAAC,uDACH;uGA3BU,WAAW,EAAA,IAAA,EAAA,EAAA,EAAA,MAAA,EAAA,EAAA,CAAA,eAAA,CAAA,SAAA,EAAA,CAAA;AAAX,IAAA,OAAA,IAAA,GAAA,EAAA,CAAA,oBAAA,CAAA,EAAA,UAAA,EAAA,QAAA,EAAA,OAAA,EAAA,QAAA,EAAA,IAAA,EAAA,WAAW,EAAA,YAAA,EAAA,IAAA,EAAA,QAAA,EAAA,eAAA,EAAA,MAAA,EAAA,EAAA,SAAA,EAAA,EAAA,iBAAA,EAAA,WAAA,EAAA,UAAA,EAAA,WAAA,EAAA,QAAA,EAAA,IAAA,EAAA,UAAA,EAAA,KAAA,EAAA,iBAAA,EAAA,IAAA,EAAA,EAAA,QAAA,EAAA,EAAA,iBAAA,EAAA,UAAA,EAAA,UAAA,EAAA,UAAA,EAAA,QAAA,EAAA,IAAA,EAAA,UAAA,EAAA,KAAA,EAAA,iBAAA,EAAA,IAAA,EAAA,EAAA,gBAAA,EAAA,EAAA,iBAAA,EAAA,kBAAA,EAAA,UAAA,EAAA,kBAAA,EAAA,QAAA,EAAA,IAAA,EAAA,UAAA,EAAA,KAAA,EAAA,iBAAA,EAAA,IAAA,EAAA,EAAA,EAAA,QAAA,EAAA,EAAA,EAAA,QAAA,EApBZ;;;;;;;;;;;;;;;;;AAiBT,EAAA,CAAA,EAAA,QAAA,EAAA,IAAA,EAAA,eAAA,EAAA,EAAA,CAAA,uBAAA,CAAA,MAAA,EAAA,CAAA;;2FAGU,WAAW,EAAA,UAAA,EAAA,CAAA;kBAtBvB,SAAS;AAAC,YAAA,IAAA,EAAA,CAAA;AACT,oBAAA,QAAQ,EAAE,eAAe;AACzB,oBAAA,QAAQ,EAAE;;;;;;;;;;;;;;;;;AAiBT,EAAA,CAAA;oBACD,eAAe,EAAE,uBAAuB,CAAC,MAAM;AAChD,iBAAA;;;ACXD;;;;;;;;;;;;;;;;;;;AAmBG;MAsCU,aAAa,CAAA;IACP,IAAI,GAAmB,MAAM,CAAC,OAAO,EAAE,EAAE,QAAQ,EAAE,IAAI,EAAE,CAAC;AAC1D,IAAA,UAAU,GAAe,MAAM,CAAC,UAAU,CAAC;AAC3C,IAAA,UAAU,GAA4B,MAAM,CAAC,UAAU,CAAC;;;IAKhE,EAAE,GAAwB,KAAK,CAAC,QAAQ,8CAAW,KAAK,EAAE,eAAe,EAAA,CAAG;;IAG5E,kBAAkB,GAA+C,KAAK,CAAC,KAAK,+DACnF,SAAS,EAAE,gBAAgB,EAAA,CAC3B;;AAGO,IAAA,uBAAuB,GAAqC,KAAK,CACxE,SAAS,mEACV;;IAGQ,uBAAuB,GAAoC,KAAK,CACvE,OAAO,oEACL,KAAK,EAAE,4BAA4B,EAAA,CACtC;;;AAKQ,IAAA,QAAQ,GAAoB,QAAQ,CAAC,MAAM,IAAI,CAAC,IAAI,EAAE,UAAU,EAAE,KAAK,IAAI,CAAC,EAAE,EAAE,oDAAC;;IAGjF,SAAS,GAA0B,QAAQ,CAAC,MACnD,IAAI,CAAC,QAAQ,EAAE,GAAG,IAAI,CAAC,IAAI,EAAE,aAAa,EAAE,GAAG,SAAS,EAAA,IAAA,SAAA,GAAA,CAAA,EAAA,SAAA,EAAA,WAAA,EAAA,CAAA,GAAA,EAAA,CAAA,CACzD;;IAGQ,QAAQ,GAAoB,QAAQ,CAC3C,MAAM,IAAI,CAAC,QAAQ,EAAE,IAAI,IAAI,CAAC,IAAI,EAAE,aAAa,EAAE,KAAK,SAAS,oDAClE;;IAGQ,qBAAqB,GAAoB,QAAQ,CACxD,MAAM,IAAI,CAAC,uBAAuB,EAAE,IAAI,IAAI,CAAC,IAAI,EAAE,iBAAiB,EAAE,IAAI,KAAK,iEAChF;;IAGQ,UAAU,GAAoB,QAAQ,CAC7C,MAAM,IAAI,CAAC,kBAAkB,EAAE,IAAI,IAAI,CAAC,IAAI,EAAE,YAAY,EAAE,IAAI,KAAK,sDACtE;;IAGQ,QAAQ,GAAkC,QAAQ,CAAC,MAC1D,IAAI,CAAC,UAAU,CAAC,aAAa,CAAC,OAAO,KAAK,IAAI,GAAG,IAAI,GAAG,cAAc,EAAA,IAAA,SAAA,GAAA,CAAA,EAAA,SAAA,EAAA,UAAA,EAAA,CAAA,GAAA,EAAA,CAAA,CACvE;;AAGQ,IAAA,QAAQ,GAAgD,QAAQ,CAAC,MAAK;AAC7E,QAAA,IAAI,CAAC,IAAI,CAAC,QAAQ,EAAE;AAAE,YAAA,OAAO,MAAM;AACnC,QAAA,OAAO,IAAI,CAAC,SAAS,EAAE,KAAK,KAAK,GAAG,WAAW,GAAG,YAAY;AAChE,IAAA,CAAC,oDAAC;;AAGO,IAAA,WAAW,GAAmB,QAAQ,CAAC,MAC9C,kBAAkB,CAAC;AACjB,QAAA,QAAQ,EAAE,CAAC,IAAI,CAAC,UAAU,EAAE;AAC5B,QAAA,MAAM,EAAE,IAAI,CAAC,QAAQ,EAAE;AACvB,QAAA,QAAQ,EAAE,IAAI,CAAC,UAAU,EAAE;AAC5B,KAAA,CAAC,uDACH;AAED,IAAA,WAAA,GAAA;AACE,QAAA,IAAI,CAAC,IAAI,CAAC,IAAI,EAAE;AACd,YAAA,MAAM,IAAI,KAAK,CAAC,4DAA4D,CAAC;QAC/E;AAEA,QAAA,IAAI,CAAC,UAAU,CAAC,SAAS,CAAC,MAAK;YAC7B,IAAI,CAAC,IAAI,EAAE,UAAU,CAAC,IAAI,CAAC,EAAE,EAAE,CAAC;AAClC,QAAA,CAAC,CAAC;IACJ;IAEA,QAAQ,GAAA;AACN,QAAA,IAAI,CAAC,IAAK,CAAC,QAAQ,CAAC,IAAI,CAAC;IAC3B;;IAIU,OAAO,GAAA;QACf,IAAI,IAAI,CAAC,UAAU,EAAE;YAAE;QACvB,IAAI,CAAC,IAAK,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,EAAE,CAAC;IAC5B;uGA1FW,aAAa,EAAA,IAAA,EAAA,EAAA,EAAA,MAAA,EAAA,EAAA,CAAA,eAAA,CAAA,SAAA,EAAA,CAAA;AAAb,IAAA,OAAA,IAAA,GAAA,EAAA,CAAA,oBAAA,CAAA,EAAA,UAAA,EAAA,QAAA,EAAA,OAAA,EAAA,QAAA,EAAA,IAAA,EAAA,aAAa,EAAA,YAAA,EAAA,IAAA,EAAA,QAAA,EAAA,iBAAA,EAAA,MAAA,EAAA,EAAA,EAAA,EAAA,EAAA,iBAAA,EAAA,IAAA,EAAA,UAAA,EAAA,eAAA,EAAA,QAAA,EAAA,IAAA,EAAA,UAAA,EAAA,IAAA,EAAA,iBAAA,EAAA,IAAA,EAAA,EAAA,kBAAA,EAAA,EAAA,iBAAA,EAAA,oBAAA,EAAA,UAAA,EAAA,oBAAA,EAAA,QAAA,EAAA,IAAA,EAAA,UAAA,EAAA,KAAA,EAAA,iBAAA,EAAA,IAAA,EAAA,EAAA,uBAAA,EAAA,EAAA,iBAAA,EAAA,yBAAA,EAAA,UAAA,EAAA,yBAAA,EAAA,QAAA,EAAA,IAAA,EAAA,UAAA,EAAA,KAAA,EAAA,iBAAA,EAAA,IAAA,EAAA,EAAA,uBAAA,EAAA,EAAA,iBAAA,EAAA,yBAAA,EAAA,UAAA,EAAA,4BAAA,EAAA,QAAA,EAAA,IAAA,EAAA,UAAA,EAAA,KAAA,EAAA,iBAAA,EAAA,IAAA,EAAA,EAAA,EAAA,IAAA,EAAA,EAAA,SAAA,EAAA,EAAA,OAAA,EAAA,WAAA,EAAA,eAAA,EAAA,WAAA,EAAA,eAAA,EAAA,oCAAA,EAAA,EAAA,UAAA,EAAA,EAAA,OAAA,EAAA,eAAA,EAAA,gBAAA,EAAA,YAAA,EAAA,WAAA,EAAA,YAAA,EAAA,eAAA,EAAA,uBAAA,EAAA,oBAAA,EAAA,sBAAA,EAAA,EAAA,EAAA,QAAA,EAAA,EAAA,EAAA,QAAA,EAlCd;;;;;;;;;;;;;;;;;;;;AAoBT,EAAA,CAAA,EAAA,QAAA,EAAA,IAAA,EAAA,YAAA,EAAA,CAAA,EAAA,IAAA,EAAA,WAAA,EAAA,IAAA,EACS,WAAW,EAAA,QAAA,EAAA,eAAA,EAAA,MAAA,EAAA,CAAA,WAAA,EAAA,UAAA,EAAA,kBAAA,CAAA,EAAA,CAAA,EAAA,eAAA,EAAA,EAAA,CAAA,uBAAA,CAAA,MAAA,EAAA,CAAA;;2FAaV,aAAa,EAAA,UAAA,EAAA,CAAA;kBArCzB,SAAS;AAAC,YAAA,IAAA,EAAA,CAAA;;AAET,oBAAA,QAAQ,EAAE,iBAAiB;AAC3B,oBAAA,QAAQ,EAAE;;;;;;;;;;;;;;;;;;;;AAoBT,EAAA,CAAA;oBACD,OAAO,EAAE,CAAC,WAAW,CAAC;oBACtB,eAAe,EAAE,uBAAuB,CAAC,MAAM;AAC/C,oBAAA,IAAI,EAAE;AACJ,wBAAA,SAAS,EAAE,eAAe;AAC1B,wBAAA,kBAAkB,EAAE,YAAY;AAChC,wBAAA,aAAa,EAAE,YAAY;AAC3B,wBAAA,iBAAiB,EAAE,uBAAuB;AAC1C,wBAAA,sBAAsB,EAAE,sBAAsB;AAC9C,wBAAA,SAAS,EAAE,WAAW;AACtB,wBAAA,iBAAiB,EAAE,WAAW;AAC9B,wBAAA,iBAAiB,EAAE,oCAAoC;AACxD,qBAAA;AACF,iBAAA;;;AC7ED;AAEA;AAaA;;ACfA;;AAEG;;;;"}
|
|
@@ -12,7 +12,7 @@ import { cva } from 'class-variance-authority';
|
|
|
12
12
|
*/
|
|
13
13
|
const spinnerVariants = cva([
|
|
14
14
|
'com-spinner__circle',
|
|
15
|
-
'inline-block shrink-0 rounded-
|
|
15
|
+
'inline-block shrink-0 rounded-pill border-solid',
|
|
16
16
|
'animate-[com-spin_0.6s_linear_infinite]',
|
|
17
17
|
], {
|
|
18
18
|
variants: {
|
|
@@ -25,11 +25,11 @@ const spinnerVariants = cva([
|
|
|
25
25
|
},
|
|
26
26
|
color: {
|
|
27
27
|
current: 'border-current/20 border-t-current',
|
|
28
|
-
primary: 'border-
|
|
29
|
-
accent: 'border-
|
|
30
|
-
warn: 'border-
|
|
31
|
-
success: 'border-
|
|
32
|
-
muted: '
|
|
28
|
+
primary: 'text-primary border-current/20 border-t-current',
|
|
29
|
+
accent: 'text-accent border-current/20 border-t-current',
|
|
30
|
+
warn: 'text-warn border-current/20 border-t-current',
|
|
31
|
+
success: 'text-success border-current/20 border-t-current',
|
|
32
|
+
muted: 'text-muted-foreground border-current/20 border-t-current',
|
|
33
33
|
},
|
|
34
34
|
},
|
|
35
35
|
defaultVariants: {
|