@letsprogram/ng-oat 0.1.1 → 0.1.3
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 +5 -7
- package/assets/oat/css/utilities.css +4 -0
- package/assets/oat/oat.min.css +16 -0
- package/fesm2022/letsprogram-ng-oat.mjs +717 -75
- package/package.json +13 -4
- package/types/letsprogram-ng-oat.d.ts +213 -25
- package/assets/oat/js/base.js +0 -107
- package/assets/oat/js/dropdown.js +0 -74
- package/assets/oat/js/index.js +0 -12
- package/assets/oat/js/sidebar.js +0 -22
- package/assets/oat/js/tabs.js +0 -94
- package/assets/oat/js/toast.js +0 -144
- package/assets/oat/js/tooltip.js +0 -36
- package/assets/oat/oat.js +0 -342
- package/assets/oat/oat.min.js +0 -267
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@letsprogram/ng-oat",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.3",
|
|
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",
|
|
@@ -36,9 +36,16 @@
|
|
|
36
36
|
"publishConfig": {
|
|
37
37
|
"access": "public"
|
|
38
38
|
},
|
|
39
|
-
"module": "fesm2022/letsprogram-ng-oat.mjs",
|
|
40
|
-
"typings": "types/letsprogram-ng-oat.d.ts",
|
|
41
39
|
"exports": {
|
|
40
|
+
"./assets/*": {
|
|
41
|
+
"default": "./assets/*"
|
|
42
|
+
},
|
|
43
|
+
"./src/lib/styles/*": {
|
|
44
|
+
"default": "./src/lib/styles/*"
|
|
45
|
+
},
|
|
46
|
+
"./src/lib/tokens/*": {
|
|
47
|
+
"default": "./src/lib/tokens/*"
|
|
48
|
+
},
|
|
42
49
|
"./package.json": {
|
|
43
50
|
"default": "./package.json"
|
|
44
51
|
},
|
|
@@ -50,5 +57,7 @@
|
|
|
50
57
|
"types": "./types/letsprogram-ng-oat-cdk.d.ts",
|
|
51
58
|
"default": "./fesm2022/letsprogram-ng-oat-cdk.mjs"
|
|
52
59
|
}
|
|
53
|
-
}
|
|
60
|
+
},
|
|
61
|
+
"module": "fesm2022/letsprogram-ng-oat.mjs",
|
|
62
|
+
"typings": "types/letsprogram-ng-oat.d.ts"
|
|
54
63
|
}
|
|
@@ -5,25 +5,35 @@ import { FormCheckboxControl, FormValueControl, ValidationError, FieldState } fr
|
|
|
5
5
|
/** Configuration for provideNgOat() */
|
|
6
6
|
interface NgOatOptions {
|
|
7
7
|
assets?: {
|
|
8
|
-
/**
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
8
|
+
/**
|
|
9
|
+
* How to load Oat CSS at runtime.
|
|
10
|
+
* - `false` (default) — CSS is loaded via angular.json styles array or styles.css import (recommended).
|
|
11
|
+
* - `'link'` — dynamically inject a `<link>` tag (requires assets glob in angular.json).
|
|
12
|
+
*/
|
|
13
|
+
css?: 'link' | false;
|
|
12
14
|
};
|
|
13
|
-
/**
|
|
14
|
-
|
|
15
|
-
|
|
15
|
+
/**
|
|
16
|
+
* Base path for vendored Oat assets when using dynamic CSS injection (`css: 'link'`).
|
|
17
|
+
* Only relevant if you opted into runtime injection AND configured an assets glob
|
|
18
|
+
* to copy files from `node_modules/@letsprogram/ng-oat/assets/oat` to this path.
|
|
19
|
+
* Default: `'assets/oat'`.
|
|
20
|
+
*/
|
|
16
21
|
basePath?: string;
|
|
17
22
|
}
|
|
18
23
|
/**
|
|
19
|
-
* Provides
|
|
24
|
+
* Provides ng-oat core initialisation.
|
|
25
|
+
*
|
|
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.
|
|
20
29
|
*
|
|
21
|
-
* Include in your app config providers array:
|
|
22
30
|
* ```ts
|
|
23
|
-
* provideNgOat()
|
|
24
|
-
* provideNgOat({ assets: { css:
|
|
25
|
-
* provideNgOat({ basePath: '/custom/oat' }) // custom asset location
|
|
31
|
+
* provideNgOat() // recommended (CSS via angular.json / styles.css)
|
|
32
|
+
* provideNgOat({ assets: { css: 'link' } }) // opt-in runtime CSS injection *
|
|
26
33
|
* ```
|
|
34
|
+
*
|
|
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' }`
|
|
27
37
|
*/
|
|
28
38
|
declare function provideNgOat(options?: NgOatOptions): EnvironmentProviders;
|
|
29
39
|
|
|
@@ -319,10 +329,12 @@ declare class NgOatSidebar {
|
|
|
319
329
|
}
|
|
320
330
|
|
|
321
331
|
/**
|
|
322
|
-
* Angular
|
|
332
|
+
* Angular directive that provides native tab behaviour on any element
|
|
333
|
+
* containing `role="tablist"` > `role="tab"` buttons and sibling
|
|
334
|
+
* `role="tabpanel"` containers.
|
|
323
335
|
*
|
|
324
|
-
*
|
|
325
|
-
*
|
|
336
|
+
* Works without oat.js — handles tab activation, ARIA attributes,
|
|
337
|
+
* panel visibility and full keyboard navigation internally.
|
|
326
338
|
*
|
|
327
339
|
* Usage:
|
|
328
340
|
* ```html
|
|
@@ -350,10 +362,13 @@ declare class NgOatTabs {
|
|
|
350
362
|
index: number;
|
|
351
363
|
tab: HTMLElement;
|
|
352
364
|
}>;
|
|
353
|
-
private
|
|
365
|
+
private tabEls;
|
|
366
|
+
private panelEls;
|
|
367
|
+
private cleanupFns;
|
|
354
368
|
constructor();
|
|
355
369
|
/** Programmatically select a tab by index */
|
|
356
370
|
selectTab(index: number): void;
|
|
371
|
+
private activate;
|
|
357
372
|
static ɵfac: _angular_core.ɵɵFactoryDeclaration<NgOatTabs, never>;
|
|
358
373
|
static ɵdir: _angular_core.ɵɵDirectiveDeclaration<NgOatTabs, "ot-tabs[ngOatTabs], [ngOatTabs]", ["ngOatTabs"], {}, { "ngOatTabChange": "ngOatTabChange"; }, never, never, true, never>;
|
|
359
374
|
}
|
|
@@ -403,9 +418,9 @@ declare class NgOatDialog {
|
|
|
403
418
|
static ɵdir: _angular_core.ɵɵDirectiveDeclaration<NgOatDialog, "dialog[ngOatDialog]", ["ngOatDialog"], {}, { "ngOatDialogClose": "ngOatDialogClose"; }, never, never, true, never>;
|
|
404
419
|
}
|
|
405
420
|
|
|
406
|
-
/** Toast placement positions
|
|
421
|
+
/** Toast placement positions */
|
|
407
422
|
type NgOatToastPlacement = 'top-left' | 'top-center' | 'top-right' | 'bottom-left' | 'bottom-center' | 'bottom-right';
|
|
408
|
-
/** Toast variants
|
|
423
|
+
/** Toast variants */
|
|
409
424
|
type NgOatToastVariant = 'info' | 'success' | 'danger' | 'warning';
|
|
410
425
|
/** Options for showing a toast */
|
|
411
426
|
interface NgOatToastOptions {
|
|
@@ -419,10 +434,11 @@ interface NgOatToastOptions {
|
|
|
419
434
|
dismissible?: boolean;
|
|
420
435
|
}
|
|
421
436
|
/**
|
|
422
|
-
* Angular service
|
|
437
|
+
* Angular service for Oat-styled toast notifications.
|
|
423
438
|
*
|
|
424
|
-
*
|
|
425
|
-
*
|
|
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.
|
|
426
442
|
*
|
|
427
443
|
* Usage:
|
|
428
444
|
* ```ts
|
|
@@ -436,7 +452,8 @@ interface NgOatToastOptions {
|
|
|
436
452
|
declare class NgOatToast {
|
|
437
453
|
private platformId;
|
|
438
454
|
private doc;
|
|
439
|
-
|
|
455
|
+
/** Cache of toast containers keyed by placement */
|
|
456
|
+
private containers;
|
|
440
457
|
success(message: string, title?: string, options?: Omit<NgOatToastOptions, 'variant'>): void;
|
|
441
458
|
info(message: string, title?: string, options?: Omit<NgOatToastOptions, 'variant'>): void;
|
|
442
459
|
warning(message: string, title?: string, options?: Omit<NgOatToastOptions, 'variant'>): void;
|
|
@@ -444,7 +461,6 @@ declare class NgOatToast {
|
|
|
444
461
|
show(message: string, title?: string, options?: NgOatToastOptions): HTMLElement | void;
|
|
445
462
|
/**
|
|
446
463
|
* Show a toast from a DOM element or template element.
|
|
447
|
-
* For Angular TemplateRef, use showTemplate() instead.
|
|
448
464
|
*/
|
|
449
465
|
showElement(element: HTMLElement, options?: NgOatToastOptions): void;
|
|
450
466
|
/**
|
|
@@ -454,6 +470,12 @@ declare class NgOatToast {
|
|
|
454
470
|
showTemplate(templateRef: TemplateRef<any>, vcr: ViewContainerRef, options?: NgOatToastOptions): void;
|
|
455
471
|
/** Dismiss toasts. If placement given, only that position; otherwise all. */
|
|
456
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;
|
|
457
479
|
/** Add a close button to a toast element */
|
|
458
480
|
private addCloseButton;
|
|
459
481
|
static ɵfac: _angular_core.ɵɵFactoryDeclaration<NgOatToast, never>;
|
|
@@ -835,6 +857,9 @@ declare class NgOatDropdownComponent {
|
|
|
835
857
|
open(): void;
|
|
836
858
|
close(): void;
|
|
837
859
|
toggle(): void;
|
|
860
|
+
/** Keyboard navigation for menu items (ArrowDown/Up/Home/End/Escape) */
|
|
861
|
+
private onKeydown;
|
|
862
|
+
private doc;
|
|
838
863
|
static ɵfac: _angular_core.ɵɵFactoryDeclaration<NgOatDropdownComponent, never>;
|
|
839
864
|
static ɵcmp: _angular_core.ɵɵComponentDeclaration<NgOatDropdownComponent, "ng-oat-dropdown", never, {}, { "openChange": "openChange"; }, never, ["[trigger]", "*"], true, never>;
|
|
840
865
|
}
|
|
@@ -1504,6 +1529,169 @@ declare class NgOatCardCarousel implements AfterViewInit, OnDestroy {
|
|
|
1504
1529
|
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>;
|
|
1505
1530
|
}
|
|
1506
1531
|
|
|
1532
|
+
type NgOatToolbarColor = 'default' | 'primary' | 'accent';
|
|
1533
|
+
/**
|
|
1534
|
+
* Angular toolbar component — like mat-toolbar, built on Oat CSS.
|
|
1535
|
+
*
|
|
1536
|
+
* Renders a fixed-position `<nav data-topnav>` that leverages Oat's built-in
|
|
1537
|
+
* topnav styling (flex, border, shadow). Content-projected slots let you
|
|
1538
|
+
* arrange Logo / nav-links / actions however you like.
|
|
1539
|
+
*
|
|
1540
|
+
* ## Slots
|
|
1541
|
+
* - **`[toolbarStart]`** — Left-aligned content (logo, brand, hamburger)
|
|
1542
|
+
* - **Default `<ng-content>`** — Center / free-form content (nav links, search)
|
|
1543
|
+
* - **`[toolbarEnd]`** — Right-aligned content (user menu, theme toggle, actions)
|
|
1544
|
+
*
|
|
1545
|
+
* ## Layout
|
|
1546
|
+
* The toolbar uses `display:flex; align-items:center` with a spacer between
|
|
1547
|
+
* the default content and the end slot, so start items anchor left and end
|
|
1548
|
+
* items anchor right automatically.
|
|
1549
|
+
*
|
|
1550
|
+
* Usage:
|
|
1551
|
+
* ```html
|
|
1552
|
+
* <ng-oat-toolbar>
|
|
1553
|
+
* <a toolbarStart routerLink="/" class="brand">🌾 MyApp</a>
|
|
1554
|
+
* <nav>
|
|
1555
|
+
* <a routerLink="/home">Home</a>
|
|
1556
|
+
* <a routerLink="/about">About</a>
|
|
1557
|
+
* </nav>
|
|
1558
|
+
* <ng-oat-dropdown toolbarEnd>
|
|
1559
|
+
* <button trigger class="ghost">👤 User ▾</button>
|
|
1560
|
+
* <a role="menuitem">Profile</a>
|
|
1561
|
+
* <a role="menuitem">Settings</a>
|
|
1562
|
+
* <hr />
|
|
1563
|
+
* <a role="menuitem">Logout</a>
|
|
1564
|
+
* </ng-oat-dropdown>
|
|
1565
|
+
* </ng-oat-toolbar>
|
|
1566
|
+
* ```
|
|
1567
|
+
*/
|
|
1568
|
+
declare class NgOatToolbar {
|
|
1569
|
+
readonly color: _angular_core.InputSignal<NgOatToolbarColor>;
|
|
1570
|
+
readonly dense: _angular_core.InputSignal<boolean>;
|
|
1571
|
+
readonly fixed: _angular_core.InputSignal<boolean>;
|
|
1572
|
+
protected attrVariant: _angular_core.Signal<"primary" | "accent" | null>;
|
|
1573
|
+
protected navClass: _angular_core.Signal<string>;
|
|
1574
|
+
static ɵfac: _angular_core.ɵɵFactoryDeclaration<NgOatToolbar, never>;
|
|
1575
|
+
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>;
|
|
1576
|
+
}
|
|
1577
|
+
/**
|
|
1578
|
+
* Toolbar row — use multiple rows stacked inside a toolbar.
|
|
1579
|
+
*
|
|
1580
|
+
* Usage:
|
|
1581
|
+
* ```html
|
|
1582
|
+
* <ng-oat-toolbar>
|
|
1583
|
+
* <ng-oat-toolbar-row>
|
|
1584
|
+
* <a toolbarStart>Brand</a>
|
|
1585
|
+
* <span toolbarEnd>Actions</span>
|
|
1586
|
+
* </ng-oat-toolbar-row>
|
|
1587
|
+
* <ng-oat-toolbar-row dense>
|
|
1588
|
+
* <nav>Sub-navigation tabs</nav>
|
|
1589
|
+
* </ng-oat-toolbar-row>
|
|
1590
|
+
* </ng-oat-toolbar>
|
|
1591
|
+
* ```
|
|
1592
|
+
*/
|
|
1593
|
+
declare class NgOatToolbarRow {
|
|
1594
|
+
static ɵfac: _angular_core.ɵɵFactoryDeclaration<NgOatToolbarRow, never>;
|
|
1595
|
+
static ɵcmp: _angular_core.ɵɵComponentDeclaration<NgOatToolbarRow, "ng-oat-toolbar-row", never, {}, {}, never, ["*"], true, never>;
|
|
1596
|
+
}
|
|
1597
|
+
|
|
1598
|
+
type NgOatTheme = 'light' | 'dark' | 'system';
|
|
1599
|
+
/** Describes one option in the theme selector. */
|
|
1600
|
+
interface NgOatThemeOption {
|
|
1601
|
+
/** The theme value written to localStorage / emitted. */
|
|
1602
|
+
value: NgOatTheme;
|
|
1603
|
+
/** Human-readable label shown in dropdown items. */
|
|
1604
|
+
label: string;
|
|
1605
|
+
/** Optional text/emoji shown instead of the built-in SVG icon. */
|
|
1606
|
+
icon?: string;
|
|
1607
|
+
}
|
|
1608
|
+
/**
|
|
1609
|
+
* Structural directive for fully-custom icon rendering.
|
|
1610
|
+
*
|
|
1611
|
+
* Place inside `<ng-oat-theme-selector>` to replace the built-in SVG icons.
|
|
1612
|
+
* The template context receives the current `NgOatThemeOption` as `$implicit`.
|
|
1613
|
+
*
|
|
1614
|
+
* ```html
|
|
1615
|
+
* <ng-oat-theme-selector>
|
|
1616
|
+
* <ng-template ngOatThemeSelectorIcon let-opt>
|
|
1617
|
+
* <my-icon [name]="opt.value" />
|
|
1618
|
+
* </ng-template>
|
|
1619
|
+
* </ng-oat-theme-selector>
|
|
1620
|
+
* ```
|
|
1621
|
+
*/
|
|
1622
|
+
declare class NgOatThemeSelectorIcon {
|
|
1623
|
+
readonly tpl: TemplateRef<any>;
|
|
1624
|
+
static ɵfac: _angular_core.ɵɵFactoryDeclaration<NgOatThemeSelectorIcon, never>;
|
|
1625
|
+
static ɵdir: _angular_core.ɵɵDirectiveDeclaration<NgOatThemeSelectorIcon, "ng-template[ngOatThemeSelectorIcon]", never, {}, {}, never, never, true, never>;
|
|
1626
|
+
}
|
|
1627
|
+
/**
|
|
1628
|
+
* Theme selector — shadcn-inspired light / dark / system toggle.
|
|
1629
|
+
*
|
|
1630
|
+
* Applies `colorScheme` on `<html>` and persists the choice to `localStorage`.
|
|
1631
|
+
* When "system" is selected it respects `prefers-color-scheme`.
|
|
1632
|
+
*
|
|
1633
|
+
* Usage:
|
|
1634
|
+
* ```html
|
|
1635
|
+
* <!-- Dropdown-style (default) -->
|
|
1636
|
+
* <ng-oat-theme-selector />
|
|
1637
|
+
*
|
|
1638
|
+
* <!-- Inline toggle group style -->
|
|
1639
|
+
* <ng-oat-theme-selector mode="toggle" />
|
|
1640
|
+
*
|
|
1641
|
+
* <!-- Listen for changes -->
|
|
1642
|
+
* <ng-oat-theme-selector (themeChange)="onTheme($event)" />
|
|
1643
|
+
* ```
|
|
1644
|
+
*/
|
|
1645
|
+
declare class NgOatThemeSelector implements OnInit {
|
|
1646
|
+
/** Display mode: dropdown menu or inline toggle group */
|
|
1647
|
+
readonly mode: _angular_core.InputSignal<"dropdown" | "toggle">;
|
|
1648
|
+
/** Initial theme (overrides localStorage if set) */
|
|
1649
|
+
readonly initialTheme: _angular_core.InputSignal<NgOatTheme | undefined>;
|
|
1650
|
+
/**
|
|
1651
|
+
* Custom theme options. Override labels, provide emoji icons, or
|
|
1652
|
+
* change the set entirely.
|
|
1653
|
+
*
|
|
1654
|
+
* ```html
|
|
1655
|
+
* <ng-oat-theme-selector
|
|
1656
|
+
* [themes]="[
|
|
1657
|
+
* { value: 'light', label: 'Day', icon: '🌅' },
|
|
1658
|
+
* { value: 'dark', label: 'Night', icon: '🌃' },
|
|
1659
|
+
* { value: 'system', label: 'Auto', icon: '🖥️' },
|
|
1660
|
+
* ]" />
|
|
1661
|
+
* ```
|
|
1662
|
+
*/
|
|
1663
|
+
readonly themes: _angular_core.InputSignal<NgOatThemeOption[]>;
|
|
1664
|
+
/** Emits when the user picks a theme */
|
|
1665
|
+
readonly themeChange: _angular_core.OutputEmitterRef<NgOatTheme>;
|
|
1666
|
+
/** Current active theme */
|
|
1667
|
+
readonly current: _angular_core.WritableSignal<NgOatTheme>;
|
|
1668
|
+
readonly open: _angular_core.WritableSignal<boolean>;
|
|
1669
|
+
/** Content-projected custom icon template */
|
|
1670
|
+
protected readonly iconTpl: _angular_core.Signal<NgOatThemeSelectorIcon | undefined>;
|
|
1671
|
+
/** Resolved themes (input or defaults) */
|
|
1672
|
+
protected resolvedThemes: _angular_core.Signal<NgOatThemeOption[]>;
|
|
1673
|
+
/** The currently active option object */
|
|
1674
|
+
protected activeOption: _angular_core.Signal<NgOatThemeOption>;
|
|
1675
|
+
private doc;
|
|
1676
|
+
private platformId;
|
|
1677
|
+
private mediaQuery;
|
|
1678
|
+
private mediaListener;
|
|
1679
|
+
/** Toggle the dropdown open/closed */
|
|
1680
|
+
toggleOpen(): void;
|
|
1681
|
+
/** Pick a theme and close the dropdown */
|
|
1682
|
+
pick(theme: NgOatTheme): void;
|
|
1683
|
+
/** Keyboard handler for Escape and arrow-key navigation inside the menu */
|
|
1684
|
+
onHostKey(e: KeyboardEvent): void;
|
|
1685
|
+
ngOnInit(): void;
|
|
1686
|
+
setTheme(theme: NgOatTheme): void;
|
|
1687
|
+
private applyResolved;
|
|
1688
|
+
private onDocClick;
|
|
1689
|
+
/** @internal */
|
|
1690
|
+
ngOnDestroy(): void;
|
|
1691
|
+
static ɵfac: _angular_core.ɵɵFactoryDeclaration<NgOatThemeSelector, never>;
|
|
1692
|
+
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>;
|
|
1693
|
+
}
|
|
1694
|
+
|
|
1507
1695
|
type NgOatInputType = 'text' | 'email' | 'password' | 'number' | 'tel' | 'url' | 'search' | 'date' | 'datetime-local' | 'time' | 'month' | 'week' | 'color';
|
|
1508
1696
|
/**
|
|
1509
1697
|
* Oat-styled text input implementing `FormValueControl<string>`.
|
|
@@ -1732,5 +1920,5 @@ interface TooltipPositioner {
|
|
|
1732
1920
|
/** DI token for tooltip positioning strategy */
|
|
1733
1921
|
declare const TOOLTIP_POSITIONER: InjectionToken<TooltipPositioner>;
|
|
1734
1922
|
|
|
1735
|
-
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 };
|
|
1736
|
-
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 };
|
|
1923
|
+
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 };
|
|
1924
|
+
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 };
|
package/assets/oat/js/base.js
DELETED
|
@@ -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);
|
package/assets/oat/js/index.js
DELETED
|
@@ -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;
|
package/assets/oat/js/sidebar.js
DELETED
|
@@ -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
|
-
});
|
package/assets/oat/js/tabs.js
DELETED
|
@@ -1,94 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* oat - Tabs Component
|
|
3
|
-
* Provides keyboard navigation and ARIA state management.
|
|
4
|
-
*
|
|
5
|
-
* Usage:
|
|
6
|
-
* <ot-tabs>
|
|
7
|
-
* <div role="tablist">
|
|
8
|
-
* <button role="tab">Tab 1</button>
|
|
9
|
-
* <button role="tab">Tab 2</button>
|
|
10
|
-
* </div>
|
|
11
|
-
* <div role="tabpanel">Content 1</div>
|
|
12
|
-
* <div role="tabpanel">Content 2</div>
|
|
13
|
-
* </ot-tabs>
|
|
14
|
-
*/
|
|
15
|
-
|
|
16
|
-
import { OtBase } from './base.js';
|
|
17
|
-
|
|
18
|
-
class OtTabs extends OtBase {
|
|
19
|
-
#tabs = [];
|
|
20
|
-
#panels = [];
|
|
21
|
-
|
|
22
|
-
init() {
|
|
23
|
-
const tablist = this.$(':scope > [role="tablist"]');
|
|
24
|
-
this.#tabs = tablist ? [...tablist.querySelectorAll('[role="tab"]')] : [];
|
|
25
|
-
this.#panels = this.$$(':scope > [role="tabpanel"]');
|
|
26
|
-
|
|
27
|
-
if (this.#tabs.length === 0 || this.#panels.length === 0) {
|
|
28
|
-
console.warn('ot-tabs: Missing tab or tabpanel elements');
|
|
29
|
-
return;
|
|
30
|
-
}
|
|
31
|
-
|
|
32
|
-
// Generate IDs and set up ARIA.
|
|
33
|
-
this.#tabs.forEach((tab, i) => {
|
|
34
|
-
const panel = this.#panels[i];
|
|
35
|
-
if (!panel) return;
|
|
36
|
-
|
|
37
|
-
const tabId = tab.id || `ot-tab-${this.uid()}`;
|
|
38
|
-
const panelId = panel.id || `ot-panel-${this.uid()}`;
|
|
39
|
-
|
|
40
|
-
tab.id = tabId;
|
|
41
|
-
panel.id = panelId;
|
|
42
|
-
tab.setAttribute('aria-controls', panelId);
|
|
43
|
-
panel.setAttribute('aria-labelledby', tabId);
|
|
44
|
-
});
|
|
45
|
-
|
|
46
|
-
tablist.addEventListener('click', this);
|
|
47
|
-
tablist.addEventListener('keydown', this);
|
|
48
|
-
|
|
49
|
-
// Find initially active tab or default to first.
|
|
50
|
-
const activeTab = this.#tabs.findIndex(t => t.ariaSelected === 'true');
|
|
51
|
-
this.#activate(activeTab >= 0 ? activeTab : 0);
|
|
52
|
-
}
|
|
53
|
-
|
|
54
|
-
onclick(e) {
|
|
55
|
-
const index = this.#tabs.indexOf(e.target.closest('[role="tab"]'));
|
|
56
|
-
if (index >= 0) this.#activate(index);
|
|
57
|
-
}
|
|
58
|
-
|
|
59
|
-
onkeydown(e) {
|
|
60
|
-
if (!e.target.closest('[role="tab"]')) return;
|
|
61
|
-
|
|
62
|
-
const next = this.keyNav(e, this.activeIndex, this.#tabs.length, 'ArrowLeft', 'ArrowRight');
|
|
63
|
-
if (next >= 0) {
|
|
64
|
-
this.#activate(next);
|
|
65
|
-
this.#tabs[next].focus();
|
|
66
|
-
}
|
|
67
|
-
}
|
|
68
|
-
|
|
69
|
-
#activate(idx) {
|
|
70
|
-
this.#tabs.forEach((tab, i) => {
|
|
71
|
-
const isActive = i === idx;
|
|
72
|
-
tab.ariaSelected = String(isActive);
|
|
73
|
-
tab.tabIndex = isActive ? 0 : -1;
|
|
74
|
-
});
|
|
75
|
-
|
|
76
|
-
this.#panels.forEach((panel, i) => {
|
|
77
|
-
panel.hidden = i !== idx;
|
|
78
|
-
});
|
|
79
|
-
|
|
80
|
-
this.emit('ot-tab-change', { index: idx, tab: this.#tabs[idx] });
|
|
81
|
-
}
|
|
82
|
-
|
|
83
|
-
get activeIndex() {
|
|
84
|
-
return this.#tabs.findIndex(t => t.ariaSelected === 'true');
|
|
85
|
-
}
|
|
86
|
-
|
|
87
|
-
set activeIndex(value) {
|
|
88
|
-
if (value >= 0 && value < this.#tabs.length) {
|
|
89
|
-
this.#activate(value);
|
|
90
|
-
}
|
|
91
|
-
}
|
|
92
|
-
}
|
|
93
|
-
|
|
94
|
-
customElements.define('ot-tabs', OtTabs);
|