@letsprogram/ng-oat 0.1.2 → 0.1.4

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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@letsprogram/ng-oat",
3
- "version": "0.1.2",
3
+ "version": "0.1.4",
4
4
  "description": "Angular component library built on top of the Oat CSS framework — signals-first, lightweight, and accessible.",
5
5
  "license": "MIT",
6
6
  "author": "SashiKumar Yadav",
@@ -7,22 +7,13 @@ interface NgOatOptions {
7
7
  assets?: {
8
8
  /**
9
9
  * How to load Oat CSS at runtime.
10
- * - `false` (default) — CSS is loaded via angular.json styles array (recommended).
10
+ * - `false` (default) — CSS is loaded via angular.json styles array or styles.css import (recommended).
11
11
  * - `'link'` — dynamically inject a `<link>` tag (requires assets glob in angular.json).
12
- * - `'import'` — reserved for future use.
13
12
  */
14
- css?: 'link' | 'import' | false;
15
- /**
16
- * How to load Oat JS at runtime.
17
- * - `false` (default) — JS is loaded via angular.json scripts array (recommended).
18
- * - `'script'` — dynamically inject a `<script>` tag (requires assets glob in angular.json).
19
- */
20
- js?: 'script' | false;
13
+ css?: 'link' | false;
21
14
  };
22
- /** Register ot-tabs/ot-dropdown custom elements from Oat JS (default: true). */
23
- registerWebComponents?: boolean;
24
15
  /**
25
- * Base path for vendored Oat assets when using dynamic injection (`css: 'link'` or `js: 'script'`).
16
+ * Base path for vendored Oat assets when using dynamic CSS injection (`css: 'link'`).
26
17
  * Only relevant if you opted into runtime injection AND configured an assets glob
27
18
  * to copy files from `node_modules/@letsprogram/ng-oat/assets/oat` to this path.
28
19
  * Default: `'assets/oat'`.
@@ -30,18 +21,19 @@ interface NgOatOptions {
30
21
  basePath?: string;
31
22
  }
32
23
  /**
33
- * Provides Oat UI core initialisation.
24
+ * Provides ng-oat core initialisation.
34
25
  *
35
- * By default, CSS and JS are **not** injected at runtime — add them via
36
- * `angular.json` `styles` / `scripts` arrays instead (recommended).
26
+ * By default, no runtime asset injection occurs — add CSS via
27
+ * `angular.json` `styles` array or `@import` in `styles.css` (recommended).
28
+ * Oat JS is no longer needed; all behavior is handled natively by Angular components.
37
29
  *
38
30
  * ```ts
39
- * provideNgOat() // recommended (CSS/JS via angular.json)
40
- * provideNgOat({ assets: { css: 'link', js: 'script' } }) // opt-in runtime injection *
31
+ * provideNgOat() // recommended (CSS via angular.json / styles.css)
32
+ * provideNgOat({ assets: { css: 'link' } }) // opt-in runtime CSS injection *
41
33
  * ```
42
34
  *
43
- * \* Runtime injection requires an assets glob in angular.json to copy files:
44
- * `{ glob: '**\/*', input: 'node_modules/@letsprogram/ng-oat/assets/oat', output: '/assets/oat' }`
35
+ * \\* Runtime injection requires an assets glob in angular.json to copy files:
36
+ * `{ glob: '**\\/*', input: 'node_modules/@letsprogram/ng-oat/assets/oat', output: '/assets/oat' }`
45
37
  */
46
38
  declare function provideNgOat(options?: NgOatOptions): EnvironmentProviders;
47
39
 
@@ -337,10 +329,12 @@ declare class NgOatSidebar {
337
329
  }
338
330
 
339
331
  /**
340
- * Angular integration for Oat's <ot-tabs> WebComponent.
332
+ * Angular directive that provides native tab behaviour on any element
333
+ * containing `role="tablist"` > `role="tab"` buttons and sibling
334
+ * `role="tabpanel"` containers.
341
335
  *
342
- * Oat's WC handles all ARIA, keyboard nav, and panel toggling.
343
- * This directive provides Angular-friendly signals and event binding.
336
+ * Works without oat.js — handles tab activation, ARIA attributes,
337
+ * panel visibility and full keyboard navigation internally.
344
338
  *
345
339
  * Usage:
346
340
  * ```html
@@ -368,10 +362,13 @@ declare class NgOatTabs {
368
362
  index: number;
369
363
  tab: HTMLElement;
370
364
  }>;
371
- private tabChangeListener;
365
+ private tabEls;
366
+ private panelEls;
367
+ private cleanupFns;
372
368
  constructor();
373
369
  /** Programmatically select a tab by index */
374
370
  selectTab(index: number): void;
371
+ private activate;
375
372
  static ɵfac: _angular_core.ɵɵFactoryDeclaration<NgOatTabs, never>;
376
373
  static ɵdir: _angular_core.ɵɵDirectiveDeclaration<NgOatTabs, "ot-tabs[ngOatTabs], [ngOatTabs]", ["ngOatTabs"], {}, { "ngOatTabChange": "ngOatTabChange"; }, never, never, true, never>;
377
374
  }
@@ -421,9 +418,9 @@ declare class NgOatDialog {
421
418
  static ɵdir: _angular_core.ɵɵDirectiveDeclaration<NgOatDialog, "dialog[ngOatDialog]", ["ngOatDialog"], {}, { "ngOatDialogClose": "ngOatDialogClose"; }, never, never, true, never>;
422
419
  }
423
420
 
424
- /** Toast placement positions (matches Oat's toast system) */
421
+ /** Toast placement positions */
425
422
  type NgOatToastPlacement = 'top-left' | 'top-center' | 'top-right' | 'bottom-left' | 'bottom-center' | 'bottom-right';
426
- /** Toast variants (matches Oat's toast system) */
423
+ /** Toast variants */
427
424
  type NgOatToastVariant = 'info' | 'success' | 'danger' | 'warning';
428
425
  /** Options for showing a toast */
429
426
  interface NgOatToastOptions {
@@ -437,10 +434,11 @@ interface NgOatToastOptions {
437
434
  dismissible?: boolean;
438
435
  }
439
436
  /**
440
- * Angular service wrapping Oat's toast notification system.
437
+ * Angular service for Oat-styled toast notifications.
441
438
  *
442
- * Delegates to `window.ot.toast()` (provided by oat.min.js).
443
- * Falls back to a no-op if Oat JS is not loaded.
439
+ * Fully native implementation no dependency on oat.js.
440
+ * Uses the Oat CSS `.toast`, `.toast-container`, `data-entering/data-exiting`
441
+ * animation patterns, and popover API for stacking.
444
442
  *
445
443
  * Usage:
446
444
  * ```ts
@@ -454,7 +452,8 @@ interface NgOatToastOptions {
454
452
  declare class NgOatToast {
455
453
  private platformId;
456
454
  private doc;
457
- private get ot();
455
+ /** Cache of toast containers keyed by placement */
456
+ private containers;
458
457
  success(message: string, title?: string, options?: Omit<NgOatToastOptions, 'variant'>): void;
459
458
  info(message: string, title?: string, options?: Omit<NgOatToastOptions, 'variant'>): void;
460
459
  warning(message: string, title?: string, options?: Omit<NgOatToastOptions, 'variant'>): void;
@@ -462,7 +461,6 @@ declare class NgOatToast {
462
461
  show(message: string, title?: string, options?: NgOatToastOptions): HTMLElement | void;
463
462
  /**
464
463
  * Show a toast from a DOM element or template element.
465
- * For Angular TemplateRef, use showTemplate() instead.
466
464
  */
467
465
  showElement(element: HTMLElement, options?: NgOatToastOptions): void;
468
466
  /**
@@ -472,6 +470,12 @@ declare class NgOatToast {
472
470
  showTemplate(templateRef: TemplateRef<any>, vcr: ViewContainerRef, options?: NgOatToastOptions): void;
473
471
  /** Dismiss toasts. If placement given, only that position; otherwise all. */
474
472
  dismiss(placement?: NgOatToastPlacement): void;
473
+ /** Get or create a toast container for the given placement */
474
+ private getContainer;
475
+ /** Show a prepared element as a toast */
476
+ private showEl;
477
+ /** Remove a toast with exit animation */
478
+ private removeToast;
475
479
  /** Add a close button to a toast element */
476
480
  private addCloseButton;
477
481
  static ɵfac: _angular_core.ɵɵFactoryDeclaration<NgOatToast, never>;
@@ -803,7 +807,8 @@ interface NgOatTableColumn {
803
807
  * <ng-oat-table
804
808
  * [columns]="[{key:'name', label:'Name'}, {key:'email', label:'Email'}]"
805
809
  * [data]="users"
806
- * [striped]="true"
810
+ * [scrollX]="true"
811
+ * [scrollY]="'320px'"
807
812
  * (rowClick)="onRowClick($event)">
808
813
  * </ng-oat-table>
809
814
  * ```
@@ -814,10 +819,12 @@ declare class NgOatTable {
814
819
  readonly striped: _angular_core.InputSignal<boolean>;
815
820
  readonly clickable: _angular_core.InputSignal<boolean>;
816
821
  readonly emptyText: _angular_core.InputSignal<string>;
822
+ readonly scrollX: _angular_core.InputSignal<boolean>;
823
+ readonly scrollY: _angular_core.InputSignal<string>;
817
824
  readonly rowClick: _angular_core.OutputEmitterRef<Record<string, any>>;
818
825
  onRowClick(row: Record<string, any>): void;
819
826
  static ɵfac: _angular_core.ɵɵFactoryDeclaration<NgOatTable, never>;
820
- static ɵcmp: _angular_core.ɵɵComponentDeclaration<NgOatTable, "ng-oat-table", never, { "columns": { "alias": "columns"; "required": true; "isSignal": true; }; "data": { "alias": "data"; "required": true; "isSignal": true; }; "striped": { "alias": "striped"; "required": false; "isSignal": true; }; "clickable": { "alias": "clickable"; "required": false; "isSignal": true; }; "emptyText": { "alias": "emptyText"; "required": false; "isSignal": true; }; }, { "rowClick": "rowClick"; }, never, never, true, never>;
827
+ static ɵcmp: _angular_core.ɵɵComponentDeclaration<NgOatTable, "ng-oat-table", never, { "columns": { "alias": "columns"; "required": true; "isSignal": true; }; "data": { "alias": "data"; "required": true; "isSignal": true; }; "striped": { "alias": "striped"; "required": false; "isSignal": true; }; "clickable": { "alias": "clickable"; "required": false; "isSignal": true; }; "emptyText": { "alias": "emptyText"; "required": false; "isSignal": true; }; "scrollX": { "alias": "scrollX"; "required": false; "isSignal": true; }; "scrollY": { "alias": "scrollY"; "required": false; "isSignal": true; }; }, { "rowClick": "rowClick"; }, never, never, true, never>;
821
828
  }
822
829
 
823
830
  /**
@@ -853,6 +860,9 @@ declare class NgOatDropdownComponent {
853
860
  open(): void;
854
861
  close(): void;
855
862
  toggle(): void;
863
+ /** Keyboard navigation for menu items (ArrowDown/Up/Home/End/Escape) */
864
+ private onKeydown;
865
+ private doc;
856
866
  static ɵfac: _angular_core.ɵɵFactoryDeclaration<NgOatDropdownComponent, never>;
857
867
  static ɵcmp: _angular_core.ɵɵComponentDeclaration<NgOatDropdownComponent, "ng-oat-dropdown", never, {}, { "openChange": "openChange"; }, never, ["[trigger]", "*"], true, never>;
858
868
  }
@@ -1522,6 +1532,169 @@ declare class NgOatCardCarousel implements AfterViewInit, OnDestroy {
1522
1532
  static ɵcmp: _angular_core.ɵɵComponentDeclaration<NgOatCardCarousel, "ng-oat-card-carousel", never, { "heading": { "alias": "heading"; "required": false; "isSignal": true; }; "ariaLabel": { "alias": "ariaLabel"; "required": false; "isSignal": true; }; "items": { "alias": "items"; "required": false; "isSignal": true; }; "showSeeAll": { "alias": "showSeeAll"; "required": false; "isSignal": true; }; "scrollAmount": { "alias": "scrollAmount"; "required": false; "isSignal": true; }; }, { "seeAllClick": "seeAllClick"; "cardClick": "cardClick"; }, never, never, true, never>;
1523
1533
  }
1524
1534
 
1535
+ type NgOatToolbarColor = 'default' | 'primary' | 'accent';
1536
+ /**
1537
+ * Angular toolbar component — like mat-toolbar, built on Oat CSS.
1538
+ *
1539
+ * Renders a fixed-position `<nav data-topnav>` that leverages Oat's built-in
1540
+ * topnav styling (flex, border, shadow). Content-projected slots let you
1541
+ * arrange Logo / nav-links / actions however you like.
1542
+ *
1543
+ * ## Slots
1544
+ * - **`[toolbarStart]`** — Left-aligned content (logo, brand, hamburger)
1545
+ * - **Default `<ng-content>`** — Center / free-form content (nav links, search)
1546
+ * - **`[toolbarEnd]`** — Right-aligned content (user menu, theme toggle, actions)
1547
+ *
1548
+ * ## Layout
1549
+ * The toolbar uses `display:flex; align-items:center` with a spacer between
1550
+ * the default content and the end slot, so start items anchor left and end
1551
+ * items anchor right automatically.
1552
+ *
1553
+ * Usage:
1554
+ * ```html
1555
+ * <ng-oat-toolbar>
1556
+ * <a toolbarStart routerLink="/" class="brand">🌾 MyApp</a>
1557
+ * <nav>
1558
+ * <a routerLink="/home">Home</a>
1559
+ * <a routerLink="/about">About</a>
1560
+ * </nav>
1561
+ * <ng-oat-dropdown toolbarEnd>
1562
+ * <button trigger class="ghost">👤 User ▾</button>
1563
+ * <a role="menuitem">Profile</a>
1564
+ * <a role="menuitem">Settings</a>
1565
+ * <hr />
1566
+ * <a role="menuitem">Logout</a>
1567
+ * </ng-oat-dropdown>
1568
+ * </ng-oat-toolbar>
1569
+ * ```
1570
+ */
1571
+ declare class NgOatToolbar {
1572
+ readonly color: _angular_core.InputSignal<NgOatToolbarColor>;
1573
+ readonly dense: _angular_core.InputSignal<boolean>;
1574
+ readonly fixed: _angular_core.InputSignal<boolean>;
1575
+ protected attrVariant: _angular_core.Signal<"primary" | "accent" | null>;
1576
+ protected navClass: _angular_core.Signal<string>;
1577
+ static ɵfac: _angular_core.ɵɵFactoryDeclaration<NgOatToolbar, never>;
1578
+ static ɵcmp: _angular_core.ɵɵComponentDeclaration<NgOatToolbar, "ng-oat-toolbar", never, { "color": { "alias": "color"; "required": false; "isSignal": true; }; "dense": { "alias": "dense"; "required": false; "isSignal": true; }; "fixed": { "alias": "fixed"; "required": false; "isSignal": true; }; }, {}, never, ["[toolbarStart]", "*", "[toolbarEnd]"], true, never>;
1579
+ }
1580
+ /**
1581
+ * Toolbar row — use multiple rows stacked inside a toolbar.
1582
+ *
1583
+ * Usage:
1584
+ * ```html
1585
+ * <ng-oat-toolbar>
1586
+ * <ng-oat-toolbar-row>
1587
+ * <a toolbarStart>Brand</a>
1588
+ * <span toolbarEnd>Actions</span>
1589
+ * </ng-oat-toolbar-row>
1590
+ * <ng-oat-toolbar-row dense>
1591
+ * <nav>Sub-navigation tabs</nav>
1592
+ * </ng-oat-toolbar-row>
1593
+ * </ng-oat-toolbar>
1594
+ * ```
1595
+ */
1596
+ declare class NgOatToolbarRow {
1597
+ static ɵfac: _angular_core.ɵɵFactoryDeclaration<NgOatToolbarRow, never>;
1598
+ static ɵcmp: _angular_core.ɵɵComponentDeclaration<NgOatToolbarRow, "ng-oat-toolbar-row", never, {}, {}, never, ["*"], true, never>;
1599
+ }
1600
+
1601
+ type NgOatTheme = 'light' | 'dark' | 'system';
1602
+ /** Describes one option in the theme selector. */
1603
+ interface NgOatThemeOption {
1604
+ /** The theme value written to localStorage / emitted. */
1605
+ value: NgOatTheme;
1606
+ /** Human-readable label shown in dropdown items. */
1607
+ label: string;
1608
+ /** Optional text/emoji shown instead of the built-in SVG icon. */
1609
+ icon?: string;
1610
+ }
1611
+ /**
1612
+ * Structural directive for fully-custom icon rendering.
1613
+ *
1614
+ * Place inside `<ng-oat-theme-selector>` to replace the built-in SVG icons.
1615
+ * The template context receives the current `NgOatThemeOption` as `$implicit`.
1616
+ *
1617
+ * ```html
1618
+ * <ng-oat-theme-selector>
1619
+ * <ng-template ngOatThemeSelectorIcon let-opt>
1620
+ * <my-icon [name]="opt.value" />
1621
+ * </ng-template>
1622
+ * </ng-oat-theme-selector>
1623
+ * ```
1624
+ */
1625
+ declare class NgOatThemeSelectorIcon {
1626
+ readonly tpl: TemplateRef<any>;
1627
+ static ɵfac: _angular_core.ɵɵFactoryDeclaration<NgOatThemeSelectorIcon, never>;
1628
+ static ɵdir: _angular_core.ɵɵDirectiveDeclaration<NgOatThemeSelectorIcon, "ng-template[ngOatThemeSelectorIcon]", never, {}, {}, never, never, true, never>;
1629
+ }
1630
+ /**
1631
+ * Theme selector — shadcn-inspired light / dark / system toggle.
1632
+ *
1633
+ * Applies `colorScheme` on `<html>` and persists the choice to `localStorage`.
1634
+ * When "system" is selected it respects `prefers-color-scheme`.
1635
+ *
1636
+ * Usage:
1637
+ * ```html
1638
+ * <!-- Dropdown-style (default) -->
1639
+ * <ng-oat-theme-selector />
1640
+ *
1641
+ * <!-- Inline toggle group style -->
1642
+ * <ng-oat-theme-selector mode="toggle" />
1643
+ *
1644
+ * <!-- Listen for changes -->
1645
+ * <ng-oat-theme-selector (themeChange)="onTheme($event)" />
1646
+ * ```
1647
+ */
1648
+ declare class NgOatThemeSelector implements OnInit {
1649
+ /** Display mode: dropdown menu or inline toggle group */
1650
+ readonly mode: _angular_core.InputSignal<"toggle" | "dropdown">;
1651
+ /** Initial theme (overrides localStorage if set) */
1652
+ readonly initialTheme: _angular_core.InputSignal<NgOatTheme | undefined>;
1653
+ /**
1654
+ * Custom theme options. Override labels, provide emoji icons, or
1655
+ * change the set entirely.
1656
+ *
1657
+ * ```html
1658
+ * <ng-oat-theme-selector
1659
+ * [themes]="[
1660
+ * { value: 'light', label: 'Day', icon: '🌅' },
1661
+ * { value: 'dark', label: 'Night', icon: '🌃' },
1662
+ * { value: 'system', label: 'Auto', icon: '🖥️' },
1663
+ * ]" />
1664
+ * ```
1665
+ */
1666
+ readonly themes: _angular_core.InputSignal<NgOatThemeOption[]>;
1667
+ /** Emits when the user picks a theme */
1668
+ readonly themeChange: _angular_core.OutputEmitterRef<NgOatTheme>;
1669
+ /** Current active theme */
1670
+ readonly current: _angular_core.WritableSignal<NgOatTheme>;
1671
+ readonly open: _angular_core.WritableSignal<boolean>;
1672
+ /** Content-projected custom icon template */
1673
+ protected readonly iconTpl: _angular_core.Signal<NgOatThemeSelectorIcon | undefined>;
1674
+ /** Resolved themes (input or defaults) */
1675
+ protected resolvedThemes: _angular_core.Signal<NgOatThemeOption[]>;
1676
+ /** The currently active option object */
1677
+ protected activeOption: _angular_core.Signal<NgOatThemeOption>;
1678
+ private doc;
1679
+ private platformId;
1680
+ private mediaQuery;
1681
+ private mediaListener;
1682
+ /** Toggle the dropdown open/closed */
1683
+ toggleOpen(): void;
1684
+ /** Pick a theme and close the dropdown */
1685
+ pick(theme: NgOatTheme): void;
1686
+ /** Keyboard handler for Escape and arrow-key navigation inside the menu */
1687
+ onHostKey(e: KeyboardEvent): void;
1688
+ ngOnInit(): void;
1689
+ setTheme(theme: NgOatTheme): void;
1690
+ private applyResolved;
1691
+ private onDocClick;
1692
+ /** @internal */
1693
+ ngOnDestroy(): void;
1694
+ static ɵfac: _angular_core.ɵɵFactoryDeclaration<NgOatThemeSelector, never>;
1695
+ static ɵcmp: _angular_core.ɵɵComponentDeclaration<NgOatThemeSelector, "ng-oat-theme-selector", never, { "mode": { "alias": "mode"; "required": false; "isSignal": true; }; "initialTheme": { "alias": "initialTheme"; "required": false; "isSignal": true; }; "themes": { "alias": "themes"; "required": false; "isSignal": true; }; }, { "themeChange": "themeChange"; }, ["iconTpl"], never, true, never>;
1696
+ }
1697
+
1525
1698
  type NgOatInputType = 'text' | 'email' | 'password' | 'number' | 'tel' | 'url' | 'search' | 'date' | 'datetime-local' | 'time' | 'month' | 'week' | 'color';
1526
1699
  /**
1527
1700
  * Oat-styled text input implementing `FormValueControl<string>`.
@@ -1750,5 +1923,5 @@ interface TooltipPositioner {
1750
1923
  /** DI token for tooltip positioning strategy */
1751
1924
  declare const TOOLTIP_POSITIONER: InjectionToken<TooltipPositioner>;
1752
1925
 
1753
- export { NG_OAT_CHIP_GROUP, NG_OAT_TOGGLE_GROUP, NgOatAccordion, NgOatAlert, NgOatAvatar, NgOatBadge, NgOatBreadcrumb, NgOatButton, NgOatCard, NgOatCardCarousel, NgOatCardFooter, NgOatCardHeader, NgOatCarousel, NgOatCheckbox, NgOatChip, NgOatChipGroup, NgOatChipInput, NgOatDialog, NgOatDialogComponent, NgOatDropdown, NgOatDropdownComponent, NgOatFileUpload, NgOatFormError, NgOatInput, NgOatInputOtp, NgOatMeter, NgOatPagination, NgOatProgress, NgOatRadioGroup, NgOatSearchInput, NgOatSelect, NgOatSeparator, NgOatSidebar, NgOatSidebarComponent, NgOatSkeleton, NgOatSpinner, NgOatSplitButton, NgOatSwitch, NgOatTable, NgOatTabs, NgOatTabsComponent, NgOatTextarea, NgOatThemeRef, NgOatToast, NgOatToggle, NgOatToggleGroup, NgOatTooltip, NgOatTooltipComponent, OAT_TOKEN_MAP, OAT_VERSION, OAT_VERSION_TOKEN, TOOLTIP_POSITIONER, provideNgOat, provideNgOatTheme };
1754
- export type { NgOatAccordionItem, NgOatAlertVariant, NgOatAvatarSize, NgOatBadgeVariant, NgOatButtonSize, NgOatButtonStyle, NgOatButtonVariant, NgOatCarouselAspectRatio, NgOatCarouselOrientation, NgOatCarouselSlide, NgOatChipGroupHost, NgOatChipSize, NgOatChipVariant, NgOatInputType, NgOatOptions, NgOatProductCard, NgOatRadioOption, NgOatSelectOption, NgOatSeparatorOrientation, NgOatSkeletonType, NgOatSpinnerSize, NgOatTabItem, NgOatTableColumn, NgOatThemeConfig, NgOatToastOptions, NgOatToastPlacement, NgOatToastVariant, NgOatToggleGroupHost, NgOatToggleGroupSize, NgOatToggleGroupVariant, NgOatToggleSize, NgOatToggleVariant, OatBreadcrumbItem, OatTokens, Placement, TooltipPositioner };
1926
+ export { NG_OAT_CHIP_GROUP, NG_OAT_TOGGLE_GROUP, NgOatAccordion, NgOatAlert, NgOatAvatar, NgOatBadge, NgOatBreadcrumb, NgOatButton, NgOatCard, NgOatCardCarousel, NgOatCardFooter, NgOatCardHeader, NgOatCarousel, NgOatCheckbox, NgOatChip, NgOatChipGroup, NgOatChipInput, NgOatDialog, NgOatDialogComponent, NgOatDropdown, NgOatDropdownComponent, NgOatFileUpload, NgOatFormError, NgOatInput, NgOatInputOtp, NgOatMeter, NgOatPagination, NgOatProgress, NgOatRadioGroup, NgOatSearchInput, NgOatSelect, NgOatSeparator, NgOatSidebar, NgOatSidebarComponent, NgOatSkeleton, NgOatSpinner, NgOatSplitButton, NgOatSwitch, NgOatTable, NgOatTabs, NgOatTabsComponent, NgOatTextarea, NgOatThemeRef, NgOatThemeSelector, NgOatThemeSelectorIcon, NgOatToast, NgOatToggle, NgOatToggleGroup, NgOatToolbar, NgOatToolbarRow, NgOatTooltip, NgOatTooltipComponent, OAT_TOKEN_MAP, OAT_VERSION, OAT_VERSION_TOKEN, TOOLTIP_POSITIONER, provideNgOat, provideNgOatTheme };
1927
+ export type { NgOatAccordionItem, NgOatAlertVariant, NgOatAvatarSize, NgOatBadgeVariant, NgOatButtonSize, NgOatButtonStyle, NgOatButtonVariant, NgOatCarouselAspectRatio, NgOatCarouselOrientation, NgOatCarouselSlide, NgOatChipGroupHost, NgOatChipSize, NgOatChipVariant, NgOatInputType, NgOatOptions, NgOatProductCard, NgOatRadioOption, NgOatSelectOption, NgOatSeparatorOrientation, NgOatSkeletonType, NgOatSpinnerSize, NgOatTabItem, NgOatTableColumn, NgOatTheme, NgOatThemeConfig, NgOatThemeOption, NgOatToastOptions, NgOatToastPlacement, NgOatToastVariant, NgOatToggleGroupHost, NgOatToggleGroupSize, NgOatToggleGroupVariant, NgOatToggleSize, NgOatToggleVariant, NgOatToolbarColor, OatBreadcrumbItem, OatTokens, Placement, TooltipPositioner };
@@ -1,107 +0,0 @@
1
- // oat - Base Web Component Class
2
- // Provides lifecycle management, event handling, and utilities.
3
-
4
- export class OtBase extends HTMLElement {
5
- #initialized = false;
6
-
7
- // Called when element is added to DOM.
8
- connectedCallback() {
9
- if (this.#initialized) return;
10
-
11
- // Wait for DOM to be ready.
12
- if (document.readyState === 'loading') {
13
- document.addEventListener('DOMContentLoaded', () => this.#setup(), { once: true });
14
- } else {
15
- this.#setup();
16
- }
17
- }
18
-
19
- // Private setup to ensure that init() is only called once.
20
- #setup() {
21
- if (this.#initialized) return;
22
- this.#initialized = true;
23
- this.init();
24
- }
25
-
26
- // Called when element is removed from DOM.
27
- disconnectedCallback() {
28
- this.cleanup();
29
- }
30
-
31
- // Override in subclass for cleanup logic.
32
- cleanup() {}
33
-
34
- // Central event handler - enables automatic cleanup.
35
- // Usage: element.addEventListener('click', this)
36
- handleEvent(event) {
37
- const handler = this[`on${event.type}`];
38
- if (handler) handler.call(this, event);
39
- }
40
-
41
- // Given a keyboard event (left, right, home, end), the current selection idx
42
- // total items in a list, return 0-n index of the next/previous item
43
- // for doing a roving keyboard nav.
44
- keyNav(event, idx, len, prevKey, nextKey, homeEnd = false) {
45
- const { key } = event;
46
- let next = -1;
47
-
48
- if (key === nextKey) {
49
- next = (idx + 1) % len;
50
- } else if (key === prevKey) {
51
- next = (idx - 1 + len) % len;
52
- } else if (homeEnd) {
53
- if (key === 'Home') {
54
- next = 0;
55
- } else if (key === 'End') {
56
- next = len - 1;
57
- }
58
- }
59
-
60
- if (next >= 0) event.preventDefault();
61
- return next;
62
- }
63
-
64
- // Emit a custom event.
65
- emit(name, detail = null) {
66
- return this.dispatchEvent(new CustomEvent(name, {
67
- bubbles: true,
68
- composed: true,
69
- cancelable: true,
70
- detail
71
- }));
72
- }
73
-
74
- // Query selector within this element.
75
- $(selector) {
76
- return this.querySelector(selector);
77
- }
78
-
79
- // Query selector all within this element.
80
- $$(selector) {
81
- return Array.from(this.querySelectorAll(selector));
82
- }
83
-
84
- // Generate a unique ID string.
85
- uid() {
86
- return Math.random().toString(36).slice(2, 10);
87
- }
88
- }
89
-
90
- // Polyfill for command/commandfor (Safari)
91
- if (!('commandForElement' in HTMLButtonElement.prototype)) {
92
- document.addEventListener('click', e => {
93
- const btn = e.target.closest('button[commandfor]');
94
- if (!btn) return;
95
-
96
- const target = document.getElementById(btn.getAttribute('commandfor'));
97
- if (!target) return;
98
-
99
- const command = btn.getAttribute('command') || 'toggle';
100
-
101
- if (target instanceof HTMLDialogElement) {
102
- if (command === 'show-modal') target.showModal();
103
- else if (command === 'close') target.close();
104
- else target.open ? target.close() : target.showModal();
105
- }
106
- });
107
- }
@@ -1,74 +0,0 @@
1
- /**
2
- * oat - Dropdown Component
3
- * Provides positioning, keyboard navigation, and ARIA state management.
4
- *
5
- * Usage:
6
- * <ot-dropdown>
7
- * <button popovertarget="menu-id">Options</button>
8
- * <menu popover id="menu-id">
9
- * <button role="menuitem">Item 1</button>
10
- * <button role="menuitem">Item 2</button>
11
- * </menu>
12
- * </ot-dropdown>
13
- */
14
-
15
- import { OtBase } from './base.js';
16
-
17
- class OtDropdown extends OtBase {
18
- #menu;
19
- #trigger;
20
- #position;
21
- #items;
22
-
23
- init() {
24
- this.#menu = this.$('[popover]');
25
- this.#trigger = this.$('[popovertarget]');
26
-
27
- if (!this.#menu || !this.#trigger) return;
28
-
29
- this.#menu.addEventListener('toggle', this);
30
- this.#menu.addEventListener('keydown', this);
31
-
32
- this.#position = () => {
33
- // Position has to be calculated and applied manually because
34
- // popover positioning is like fixed, relative to the window.
35
- const r = this.#trigger.getBoundingClientRect();
36
- const m = this.#menu.getBoundingClientRect();
37
-
38
- // Flip if menu overflows viewport.
39
- this.#menu.style.top = `${r.bottom + m.height > window.innerHeight ? r.top - m.height : r.bottom}px`;
40
- this.#menu.style.left = `${r.left + m.width > window.innerWidth ? r.right - m.width : r.left}px`;
41
- };
42
- }
43
-
44
- ontoggle(e) {
45
- if (e.newState === 'open') {
46
- this.#position();
47
- window.addEventListener('scroll', this.#position, true);
48
- window.addEventListener('resize', this.#position);
49
- this.#items = this.$$('[role="menuitem"]');
50
- this.#items[0]?.focus();
51
- this.#trigger.ariaExpanded = 'true';
52
- } else {
53
- this.cleanup();
54
- this.#items = null;
55
- this.#trigger.ariaExpanded = 'false';
56
- this.#trigger.focus();
57
- }
58
- }
59
-
60
- onkeydown(e) {
61
- if (!e.target.matches('[role="menuitem"]')) return;
62
-
63
- const idx = this.#items.indexOf(e.target);
64
- const next = this.keyNav(e, idx, this.#items.length, 'ArrowUp', 'ArrowDown', true);
65
- if (next >= 0) this.#items[next].focus();
66
- }
67
-
68
- cleanup() {
69
- window.removeEventListener('scroll', this.#position, true);
70
- window.removeEventListener('resize', this.#position);
71
- }
72
- }
73
-
74
- customElements.define('ot-dropdown', OtDropdown);
@@ -1,12 +0,0 @@
1
- import './base.js';
2
- import './tabs.js';
3
- import './dropdown.js';
4
- import './tooltip.js';
5
- import './sidebar.js';
6
- import { toast, toastEl, toastClear } from './toast.js';
7
-
8
- // Register the global window.ot.* APIs.
9
- const ot = window.ot || (window.ot = {});
10
- ot.toast = toast;
11
- ot.toast.el = toastEl;
12
- ot.toast.clear = toastClear;
@@ -1,22 +0,0 @@
1
- /**
2
- * Sidebar toggle handler
3
- * Toggles data-sidebar-open on layout when toggle button is clicked
4
- */
5
- document.addEventListener('click', (e) => {
6
- const toggle = e.target.closest('[data-sidebar-toggle]');
7
- if (toggle) {
8
- const layout = toggle.closest('[data-sidebar-layout]');
9
- layout?.toggleAttribute('data-sidebar-open');
10
- return;
11
- }
12
-
13
- // Dismiss sidebar when clicking outside (when sidebar is not an overlay).
14
- if (!e.target.closest('[data-sidebar]')) {
15
- const layout = document.querySelector('[data-sidebar-layout][data-sidebar-open]');
16
- // Hardcode breakpoint (for now) as there's no way to use a CSS variable in
17
- // the @media{} query which could've been picked up here.
18
- if (layout && window.matchMedia('(max-width: 768px)').matches) {
19
- layout.removeAttribute('data-sidebar-open');
20
- }
21
- }
22
- });