@newthink/ui 0.0.1 → 0.1.1

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.
@@ -0,0 +1,2 @@
1
+ export declare const tabs: import("./headless").HeadlessComponent;
2
+ //# sourceMappingURL=tabs.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"tabs.d.ts","sourceRoot":"","sources":["../../src/headless/tabs.ts"],"names":[],"mappings":"AAEA,eAAO,MAAM,IAAI,wCAkDhB,CAAC"}
@@ -0,0 +1,43 @@
1
+ import { headless } from './headless';
2
+ export const tabs = headless('tabs', (_el, _directive, { Alpine, evaluate }) => {
3
+ const tabGroup = Alpine.reactive({
4
+ activeTab: 0,
5
+ isSelected($el) {
6
+ return this.tabs[this.activeTab] === $el;
7
+ },
8
+ tabs: [],
9
+ panels: [],
10
+ $focus: evaluate('$focus'),
11
+ });
12
+ return tabGroup;
13
+ }, {
14
+ list: (tabGroup, el, _directive, { Alpine }) => {
15
+ const focusNext = () => tabGroup.$focus.wrap().next();
16
+ const focusPrevious = () => tabGroup.$focus.wrap().previous();
17
+ Alpine.bind(el, {
18
+ ':role': () => 'tablist',
19
+ '@keydown.arrow-left.stop.prevent': focusPrevious,
20
+ '@keydown.arrow-right.stop.prevent': focusNext,
21
+ '@keydown.arrow-up.stop.prevent': focusPrevious,
22
+ '@keydown.arrow-down.stop.prevent': focusNext,
23
+ });
24
+ },
25
+ tab: (tabGroup, el, _directive, { Alpine }) => {
26
+ const tabIndex = tabGroup.tabs.push(el) - 1;
27
+ Alpine.bind(el, {
28
+ ':tabindex': () => Number(tabIndex === tabGroup.activeTab) - 1,
29
+ ':aria-selected': () => tabIndex === tabGroup.activeTab,
30
+ '@click': () => tabGroup.$focus.focus(el),
31
+ '@focus': () => (tabGroup.activeTab = tabIndex),
32
+ });
33
+ },
34
+ panel: (tabGroup, el, _directive, { Alpine }) => {
35
+ const panelIndex = tabGroup.panels.push(el) - 1;
36
+ Alpine.bind(el, {
37
+ 'x-show': () => panelIndex === tabGroup.activeTab,
38
+ ':hidden': () => panelIndex !== tabGroup.activeTab,
39
+ ':aria-hidden': () => panelIndex !== tabGroup.activeTab,
40
+ });
41
+ },
42
+ });
43
+ //# sourceMappingURL=tabs.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"tabs.js","sourceRoot":"","sources":["../../src/headless/tabs.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,MAAM,YAAY,CAAC;AAEtC,MAAM,CAAC,MAAM,IAAI,GAAG,QAAQ,CAC1B,MAAM,EACN,CAAC,GAAG,EAAE,UAAU,EAAE,EAAE,MAAM,EAAE,QAAQ,EAAE,EAAE,EAAE;IACxC,MAAM,QAAQ,GAKV,MAAM,CAAC,QAAQ,CAAC;QAClB,SAAS,EAAE,CAAC;QACZ,UAAU,CAAC,GAAgB;YACzB,OAAO,IAAI,CAAC,IAAI,CAAC,IAAI,CAAC,SAAS,CAAC,KAAK,GAAG,CAAC;QAC3C,CAAC;QACD,IAAI,EAAE,EAAmB;QACzB,MAAM,EAAE,EAAmB;QAC3B,MAAM,EAAE,QAAQ,CAAC,QAAQ,CAAe;KACzC,CAAC,CAAC;IACH,OAAO,QAAQ,CAAC;AAClB,CAAC,EACD;IACE,IAAI,EAAE,CAAC,QAAQ,EAAE,EAAE,EAAE,UAAU,EAAE,EAAE,MAAM,EAAE,EAAE,EAAE;QAC7C,MAAM,SAAS,GAAG,GAAG,EAAE,CAAC,QAAQ,CAAC,MAAM,CAAC,IAAI,EAAE,CAAC,IAAI,EAAE,CAAC;QACtD,MAAM,aAAa,GAAG,GAAG,EAAE,CAAC,QAAQ,CAAC,MAAM,CAAC,IAAI,EAAE,CAAC,QAAQ,EAAE,CAAC;QAE9D,MAAM,CAAC,IAAI,CAAC,EAAE,EAAE;YACd,OAAO,EAAE,GAAG,EAAE,CAAC,SAAS;YACxB,kCAAkC,EAAE,aAAa;YACjD,mCAAmC,EAAE,SAAS;YAC9C,gCAAgC,EAAE,aAAa;YAC/C,kCAAkC,EAAE,SAAS;SAC9C,CAAC,CAAC;IACL,CAAC;IACD,GAAG,EAAE,CAAC,QAAQ,EAAE,EAAE,EAAE,UAAU,EAAE,EAAE,MAAM,EAAE,EAAE,EAAE;QAC5C,MAAM,QAAQ,GAAG,QAAQ,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,CAAC,GAAG,CAAC,CAAC;QAC5C,MAAM,CAAC,IAAI,CAAC,EAAE,EAAE;YACd,WAAW,EAAE,GAAG,EAAE,CAAC,MAAM,CAAC,QAAQ,KAAK,QAAQ,CAAC,SAAS,CAAC,GAAG,CAAC;YAC9D,gBAAgB,EAAE,GAAG,EAAE,CAAC,QAAQ,KAAK,QAAQ,CAAC,SAAS;YACvD,QAAQ,EAAE,GAAG,EAAE,CAAC,QAAQ,CAAC,MAAM,CAAC,KAAK,CAAC,EAAE,CAAC;YACzC,QAAQ,EAAE,GAAG,EAAE,CAAC,CAAC,QAAQ,CAAC,SAAS,GAAG,QAAQ,CAAC;SAChD,CAAC,CAAC;IACL,CAAC;IACD,KAAK,EAAE,CAAC,QAAQ,EAAE,EAAE,EAAE,UAAU,EAAE,EAAE,MAAM,EAAE,EAAE,EAAE;QAC9C,MAAM,UAAU,GAAG,QAAQ,CAAC,MAAM,CAAC,IAAI,CAAC,EAAE,CAAC,GAAG,CAAC,CAAC;QAChD,MAAM,CAAC,IAAI,CAAC,EAAE,EAAE;YACd,QAAQ,EAAE,GAAG,EAAE,CAAC,UAAU,KAAK,QAAQ,CAAC,SAAS;YACjD,SAAS,EAAE,GAAG,EAAE,CAAC,UAAU,KAAK,QAAQ,CAAC,SAAS;YAClD,cAAc,EAAE,GAAG,EAAE,CAAC,UAAU,KAAK,QAAQ,CAAC,SAAS;SACxD,CAAC,CAAC;IACL,CAAC;CACF,CACF,CAAC"}
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,iBAAiB,EAAE,MAAM,qBAAqB,CAAC;AAGxD,eAAO,MAAM,EAAE,EAAE,iBAAsD,CAAC;AAExE,eAAe,EAAE,CAAC"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,iBAAiB,EAAE,MAAM,qBAAqB,CAAC;AAIxD,eAAO,MAAM,EAAE,EAAE,iBAA4D,CAAC;AAE9E,eAAe,EAAE,CAAC"}
package/dist/index.js CHANGED
@@ -1,4 +1,5 @@
1
1
  import { panel } from './headless/panel';
2
- export const UI = (Alpine) => Alpine.plugin([panel]);
2
+ import { tabs } from './headless/tabs';
3
+ export const UI = (Alpine) => Alpine.plugin([panel, tabs]);
3
4
  export default UI;
4
5
  //# sourceMappingURL=index.js.map
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,KAAK,EAAE,MAAM,kBAAkB,CAAC;AAEzC,MAAM,CAAC,MAAM,EAAE,GAAsB,CAAC,MAAM,EAAE,EAAE,CAAC,MAAM,CAAC,MAAM,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC;AAExE,eAAe,EAAE,CAAC"}
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,KAAK,EAAE,MAAM,kBAAkB,CAAC;AACzC,OAAO,EAAE,IAAI,EAAE,MAAM,iBAAiB,CAAC;AAEvC,MAAM,CAAC,MAAM,EAAE,GAAsB,CAAC,MAAM,EAAE,EAAE,CAAC,MAAM,CAAC,MAAM,CAAC,CAAC,KAAK,EAAE,IAAI,CAAC,CAAC,CAAC;AAE9E,eAAe,EAAE,CAAC"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@newthink/ui",
3
- "version": "0.0.1",
3
+ "version": "0.1.1",
4
4
  "description": "Simple Alpine Headless UI Components",
5
5
  "exports": {
6
6
  ".": {
@@ -19,7 +19,7 @@
19
19
  "license": "ISC",
20
20
  "devDependencies": {
21
21
  "@trivago/prettier-plugin-sort-imports": "4.1.1",
22
- "@types/node": "20.2.3",
22
+ "@types/node": "20.2.5",
23
23
  "@typescript-eslint/eslint-plugin": "5.59.7",
24
24
  "@typescript-eslint/parser": "5.59.7",
25
25
  "@vitest/coverage-c8": "0.31.1",
@@ -32,12 +32,13 @@
32
32
  "prettier": "2.8.8",
33
33
  "pretty-bytes": "^6.1.0",
34
34
  "typescript": "5.0.4",
35
- "vite": "4.3.8",
35
+ "vite": "4.3.9",
36
36
  "vite-tsconfig-paths": "4.2.0",
37
37
  "vitest": "0.31.1"
38
38
  },
39
39
  "peerDependencies": {
40
- "alpinejs": "^3.10.0"
40
+ "alpinejs": "^3.10.0",
41
+ "@alpinejs/focus": "^3.10.0"
41
42
  },
42
43
  "prettier": {
43
44
  "singleQuote": true,
@@ -0,0 +1,79 @@
1
+ import { headless } from './headless';
2
+
3
+ export const tabs = headless(
4
+ 'tabs',
5
+ (_el, _directive, { Alpine, evaluate }) => {
6
+ const tabGroup: {
7
+ activeTab: number;
8
+ tabs: HTMLElement[];
9
+ panels: HTMLElement[];
10
+ $focus: FocusMagic;
11
+ } = Alpine.reactive({
12
+ activeTab: 0,
13
+ isSelected($el: HTMLElement): boolean {
14
+ return this.tabs[this.activeTab] === $el;
15
+ },
16
+ tabs: [] as HTMLElement[],
17
+ panels: [] as HTMLElement[],
18
+ $focus: evaluate('$focus') as FocusMagic,
19
+ });
20
+ return tabGroup;
21
+ },
22
+ {
23
+ list: (tabGroup, el, _directive, { Alpine }) => {
24
+ const focusNext = () => tabGroup.$focus.wrap().next();
25
+ const focusPrevious = () => tabGroup.$focus.wrap().previous();
26
+
27
+ Alpine.bind(el, {
28
+ ':role': () => 'tablist',
29
+ '@keydown.arrow-left.stop.prevent': focusPrevious,
30
+ '@keydown.arrow-right.stop.prevent': focusNext,
31
+ '@keydown.arrow-up.stop.prevent': focusPrevious,
32
+ '@keydown.arrow-down.stop.prevent': focusNext,
33
+ });
34
+ },
35
+ tab: (tabGroup, el, _directive, { Alpine }) => {
36
+ const tabIndex = tabGroup.tabs.push(el) - 1;
37
+ Alpine.bind(el, {
38
+ ':tabindex': () => Number(tabIndex === tabGroup.activeTab) - 1,
39
+ ':aria-selected': () => tabIndex === tabGroup.activeTab,
40
+ '@click': () => tabGroup.$focus.focus(el),
41
+ '@focus': () => (tabGroup.activeTab = tabIndex),
42
+ });
43
+ },
44
+ panel: (tabGroup, el, _directive, { Alpine }) => {
45
+ const panelIndex = tabGroup.panels.push(el) - 1;
46
+ Alpine.bind(el, {
47
+ 'x-show': () => panelIndex === tabGroup.activeTab,
48
+ ':hidden': () => panelIndex !== tabGroup.activeTab,
49
+ ':aria-hidden': () => panelIndex !== tabGroup.activeTab,
50
+ });
51
+ },
52
+ }
53
+ );
54
+
55
+ type FocusMagic = {
56
+ within(el: HTMLElement): FocusMagic;
57
+ withoutScrolling(): FocusMagic;
58
+ noscroll(): FocusMagic;
59
+ withWrapAround(): FocusMagic;
60
+ wrap(): FocusMagic;
61
+ focusable(el: HTMLElement): boolean;
62
+ previouslyFocused(): HTMLElement;
63
+ lastFocused(): HTMLElement;
64
+ focused(): HTMLElement;
65
+ focusables(): HTMLElement[];
66
+ all(): HTMLElement[];
67
+ isFirst(el: HTMLElement): boolean;
68
+ isLast(el: HTMLElement): boolean;
69
+ getFirst(): HTMLElement;
70
+ getLast(): HTMLElement;
71
+ getNext(): HTMLElement;
72
+ getPrevious(): HTMLElement;
73
+ first(): HTMLElement;
74
+ last(): HTMLElement;
75
+ next(): HTMLElement;
76
+ previous(): HTMLElement;
77
+ prev(): HTMLElement;
78
+ focus(el: HTMLElement): void;
79
+ };
package/src/index.ts CHANGED
@@ -1,6 +1,7 @@
1
1
  import { HeadlessComponent } from './headless/headless';
2
2
  import { panel } from './headless/panel';
3
+ import { tabs } from './headless/tabs';
3
4
 
4
- export const UI: HeadlessComponent = (Alpine) => Alpine.plugin([panel]);
5
+ export const UI: HeadlessComponent = (Alpine) => Alpine.plugin([panel, tabs]);
5
6
 
6
7
  export default UI;