@foldkit/ui 0.123.0 → 0.124.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/dist/index.d.ts CHANGED
@@ -12,6 +12,7 @@ export * as FileDrop from './fileDrop/public.js';
12
12
  export * as Input from './input/public.js';
13
13
  export * as Listbox from './listbox/public.js';
14
14
  export * as Menu from './menu/public.js';
15
+ export * as Nav from './nav/public.js';
15
16
  export * as Popover from './popover/public.js';
16
17
  export * as RadioGroup from './radioGroup/public.js';
17
18
  export * as Select from './select/public.js';
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,SAAS,MAAM,uBAAuB,CAAA;AAClD,OAAO,KAAK,MAAM,MAAM,oBAAoB,CAAA;AAC5C,OAAO,KAAK,QAAQ,MAAM,sBAAsB,CAAA;AAChD,OAAO,KAAK,UAAU,MAAM,wBAAwB,CAAA;AACpD,OAAO,KAAK,QAAQ,MAAM,sBAAsB,CAAA;AAChD,OAAO,KAAK,QAAQ,MAAM,sBAAsB,CAAA;AAChD,OAAO,KAAK,MAAM,MAAM,oBAAoB,CAAA;AAC5C,OAAO,KAAK,WAAW,MAAM,yBAAyB,CAAA;AACtD,OAAO,KAAK,UAAU,MAAM,wBAAwB,CAAA;AACpD,OAAO,KAAK,QAAQ,MAAM,sBAAsB,CAAA;AAChD,OAAO,KAAK,QAAQ,MAAM,sBAAsB,CAAA;AAChD,OAAO,KAAK,KAAK,MAAM,mBAAmB,CAAA;AAC1C,OAAO,KAAK,OAAO,MAAM,qBAAqB,CAAA;AAC9C,OAAO,KAAK,IAAI,MAAM,kBAAkB,CAAA;AACxC,OAAO,KAAK,OAAO,MAAM,qBAAqB,CAAA;AAC9C,OAAO,KAAK,UAAU,MAAM,wBAAwB,CAAA;AACpD,OAAO,KAAK,MAAM,MAAM,oBAAoB,CAAA;AAC5C,OAAO,KAAK,MAAM,MAAM,oBAAoB,CAAA;AAC5C,OAAO,KAAK,MAAM,MAAM,oBAAoB,CAAA;AAC5C,OAAO,KAAK,QAAQ,MAAM,sBAAsB,CAAA;AAChD,OAAO,KAAK,IAAI,MAAM,kBAAkB,CAAA;AACxC,OAAO,KAAK,KAAK,MAAM,mBAAmB,CAAA;AAC1C,OAAO,KAAK,OAAO,MAAM,qBAAqB,CAAA;AAC9C,OAAO,KAAK,WAAW,MAAM,yBAAyB,CAAA"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,SAAS,MAAM,uBAAuB,CAAA;AAClD,OAAO,KAAK,MAAM,MAAM,oBAAoB,CAAA;AAC5C,OAAO,KAAK,QAAQ,MAAM,sBAAsB,CAAA;AAChD,OAAO,KAAK,UAAU,MAAM,wBAAwB,CAAA;AACpD,OAAO,KAAK,QAAQ,MAAM,sBAAsB,CAAA;AAChD,OAAO,KAAK,QAAQ,MAAM,sBAAsB,CAAA;AAChD,OAAO,KAAK,MAAM,MAAM,oBAAoB,CAAA;AAC5C,OAAO,KAAK,WAAW,MAAM,yBAAyB,CAAA;AACtD,OAAO,KAAK,UAAU,MAAM,wBAAwB,CAAA;AACpD,OAAO,KAAK,QAAQ,MAAM,sBAAsB,CAAA;AAChD,OAAO,KAAK,QAAQ,MAAM,sBAAsB,CAAA;AAChD,OAAO,KAAK,KAAK,MAAM,mBAAmB,CAAA;AAC1C,OAAO,KAAK,OAAO,MAAM,qBAAqB,CAAA;AAC9C,OAAO,KAAK,IAAI,MAAM,kBAAkB,CAAA;AACxC,OAAO,KAAK,GAAG,MAAM,iBAAiB,CAAA;AACtC,OAAO,KAAK,OAAO,MAAM,qBAAqB,CAAA;AAC9C,OAAO,KAAK,UAAU,MAAM,wBAAwB,CAAA;AACpD,OAAO,KAAK,MAAM,MAAM,oBAAoB,CAAA;AAC5C,OAAO,KAAK,MAAM,MAAM,oBAAoB,CAAA;AAC5C,OAAO,KAAK,MAAM,MAAM,oBAAoB,CAAA;AAC5C,OAAO,KAAK,QAAQ,MAAM,sBAAsB,CAAA;AAChD,OAAO,KAAK,IAAI,MAAM,kBAAkB,CAAA;AACxC,OAAO,KAAK,KAAK,MAAM,mBAAmB,CAAA;AAC1C,OAAO,KAAK,OAAO,MAAM,qBAAqB,CAAA;AAC9C,OAAO,KAAK,WAAW,MAAM,yBAAyB,CAAA"}
package/dist/index.js CHANGED
@@ -12,6 +12,7 @@ export * as FileDrop from './fileDrop/public.js';
12
12
  export * as Input from './input/public.js';
13
13
  export * as Listbox from './listbox/public.js';
14
14
  export * as Menu from './menu/public.js';
15
+ export * as Nav from './nav/public.js';
15
16
  export * as Popover from './popover/public.js';
16
17
  export * as RadioGroup from './radioGroup/public.js';
17
18
  export * as Select from './select/public.js';
@@ -0,0 +1,49 @@
1
+ import { type ChildAttribute, type Html } from 'foldkit/html';
2
+ /** Per-item render info passed to the consumer's `toView`. Generic over
3
+ * `Value extends string`: the item value is typed as the consumer's union
4
+ * (typically a route tag) so `toView` can switch on it without casting. */
5
+ export type ItemInfo<Value extends string = string> = Readonly<{
6
+ value: Value;
7
+ index: number;
8
+ isCurrent: boolean;
9
+ link: ReadonlyArray<ChildAttribute>;
10
+ }>;
11
+ /** Render-time payload published to the consumer's `toView`.
12
+ *
13
+ * - `nav`: ARIA attributes for the wrapping navigation landmark. Carries
14
+ * `aria-label` only; the `<nav>` element already supplies the navigation
15
+ * role, so spread this onto an `h.nav`.
16
+ * - `items`: one entry per `viewInputs.items`, in the same order, each with
17
+ * the anchor's attribute bundle and derived current state. */
18
+ export type RenderInfo<Value extends string = string> = Readonly<{
19
+ nav: ReadonlyArray<ChildAttribute>;
20
+ items: ReadonlyArray<ItemInfo<Value>>;
21
+ }>;
22
+ /** View inputs for `Nav.view`. Generic over `Value extends string` so the
23
+ * consumer's section/route union flows into `toView`, `toHref`, and
24
+ * `isItemCurrent` without casting. */
25
+ export type ViewInputs<Value extends string = string> = Readonly<{
26
+ items: ReadonlyArray<Value>;
27
+ ariaLabel: string;
28
+ toHref: (value: Value, index: number) => string;
29
+ isItemCurrent: (value: Value, index: number) => boolean;
30
+ toView: (render: RenderInfo<Value>) => Html;
31
+ }>;
32
+ /** Renders a navigation landmark whose items are links, marking the current
33
+ * destination with `aria-current="page"`. Stateless: the current item is
34
+ * derived from `isItemCurrent`, which the consumer drives from the URL, the
35
+ * single source of truth for which page is showing.
36
+ *
37
+ * Use this for URL-driven navigation where each section is a separate
38
+ * route with its own URL, deep-linking, and browser-history behavior.
39
+ * Reach for `Tabs` instead when switching content within a single page;
40
+ * `Tabs` carries the `tablist`/`tab`/`tabpanel` semantics, which are
41
+ * wrong for URL-driven navigation.
42
+ *
43
+ * Headless: `toView` owns all markup, spreading the `nav` bundle onto an
44
+ * `h.nav` and each `item.link` bundle onto an `h.a`. Keyboard support is the
45
+ * browser's native link handling (Tab to move, Enter to follow); no roving
46
+ * tabindex is imposed, since that is a composite-widget pattern, not a
47
+ * navigation-landmark one. */
48
+ export declare const view: <Value extends string = string>(viewInputs: ViewInputs<Value>) => Html;
49
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/nav/index.ts"],"names":[],"mappings":"AACA,OAAO,EACL,KAAK,cAAc,EACnB,KAAK,IAAI,EAGV,MAAM,cAAc,CAAA;AAIrB;;4EAE4E;AAC5E,MAAM,MAAM,QAAQ,CAAC,KAAK,SAAS,MAAM,GAAG,MAAM,IAAI,QAAQ,CAAC;IAC7D,KAAK,EAAE,KAAK,CAAA;IACZ,KAAK,EAAE,MAAM,CAAA;IACb,SAAS,EAAE,OAAO,CAAA;IAClB,IAAI,EAAE,aAAa,CAAC,cAAc,CAAC,CAAA;CACpC,CAAC,CAAA;AAEF;;;;;;iEAMiE;AACjE,MAAM,MAAM,UAAU,CAAC,KAAK,SAAS,MAAM,GAAG,MAAM,IAAI,QAAQ,CAAC;IAC/D,GAAG,EAAE,aAAa,CAAC,cAAc,CAAC,CAAA;IAClC,KAAK,EAAE,aAAa,CAAC,QAAQ,CAAC,KAAK,CAAC,CAAC,CAAA;CACtC,CAAC,CAAA;AAEF;;uCAEuC;AACvC,MAAM,MAAM,UAAU,CAAC,KAAK,SAAS,MAAM,GAAG,MAAM,IAAI,QAAQ,CAAC;IAC/D,KAAK,EAAE,aAAa,CAAC,KAAK,CAAC,CAAA;IAC3B,SAAS,EAAE,MAAM,CAAA;IACjB,MAAM,EAAE,CAAC,KAAK,EAAE,KAAK,EAAE,KAAK,EAAE,MAAM,KAAK,MAAM,CAAA;IAC/C,aAAa,EAAE,CAAC,KAAK,EAAE,KAAK,EAAE,KAAK,EAAE,MAAM,KAAK,OAAO,CAAA;IACvD,MAAM,EAAE,CAAC,MAAM,EAAE,UAAU,CAAC,KAAK,CAAC,KAAK,IAAI,CAAA;CAC5C,CAAC,CAAA;AAMF;;;;;;;;;;;;;;;+BAe+B;AAC/B,eAAO,MAAM,IAAI,GAAI,KAAK,SAAS,MAAM,GAAG,MAAM,EAChD,YAAY,UAAU,CAAC,KAAK,CAAC,KAC5B,IAmCF,CAAA"}
@@ -0,0 +1,43 @@
1
+ import { Array, Option } from 'effect';
2
+ import { childAttributes, html, } from 'foldkit/html';
3
+ // VIEW
4
+ const ARIA_CURRENT_PAGE = 'page';
5
+ /** Renders a navigation landmark whose items are links, marking the current
6
+ * destination with `aria-current="page"`. Stateless: the current item is
7
+ * derived from `isItemCurrent`, which the consumer drives from the URL, the
8
+ * single source of truth for which page is showing.
9
+ *
10
+ * Use this for URL-driven navigation where each section is a separate
11
+ * route with its own URL, deep-linking, and browser-history behavior.
12
+ * Reach for `Tabs` instead when switching content within a single page;
13
+ * `Tabs` carries the `tablist`/`tab`/`tabpanel` semantics, which are
14
+ * wrong for URL-driven navigation.
15
+ *
16
+ * Headless: `toView` owns all markup, spreading the `nav` bundle onto an
17
+ * `h.nav` and each `item.link` bundle onto an `h.a`. Keyboard support is the
18
+ * browser's native link handling (Tab to move, Enter to follow); no roving
19
+ * tabindex is imposed, since that is a composite-widget pattern, not a
20
+ * navigation-landmark one. */
21
+ export const view = (viewInputs) => {
22
+ const h = html();
23
+ const { items, ariaLabel, toHref, isItemCurrent, toView } = viewInputs;
24
+ const itemInfos = Array.map(items, (value, index) => {
25
+ const isCurrent = isItemCurrent(value, index);
26
+ const maybeCurrentAttributes = Option.liftPredicate([h.AriaCurrent(ARIA_CURRENT_PAGE), h.DataAttribute('current', '')], () => isCurrent);
27
+ const linkAttributes = [
28
+ h.Href(toHref(value, index)),
29
+ ...Option.getOrElse(maybeCurrentAttributes, () => []),
30
+ ];
31
+ return {
32
+ value,
33
+ index,
34
+ isCurrent,
35
+ link: childAttributes(linkAttributes),
36
+ };
37
+ });
38
+ const navAttributes = [h.AriaLabel(ariaLabel)];
39
+ return toView({
40
+ nav: childAttributes(navAttributes),
41
+ items: itemInfos,
42
+ });
43
+ };
@@ -0,0 +1,3 @@
1
+ export { view } from './index.js';
2
+ export type { ItemInfo, RenderInfo, ViewInputs } from './index.js';
3
+ //# sourceMappingURL=public.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"public.d.ts","sourceRoot":"","sources":["../../src/nav/public.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,IAAI,EAAE,MAAM,YAAY,CAAA;AAEjC,YAAY,EAAE,QAAQ,EAAE,UAAU,EAAE,UAAU,EAAE,MAAM,YAAY,CAAA"}
@@ -0,0 +1 @@
1
+ export { view } from './index.js';
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@foldkit/ui",
3
- "version": "0.123.0",
3
+ "version": "0.124.0",
4
4
  "description": "Headless, accessible UI components for Foldkit",
5
5
  "type": "module",
6
6
  "main": "./dist/index.js",
@@ -127,7 +127,7 @@
127
127
  "typedoc": "^0.28.19",
128
128
  "typescript": "^6.0.3",
129
129
  "vitest": "^4.1.9",
130
- "foldkit": "0.123.0"
130
+ "foldkit": "0.124.0"
131
131
  },
132
132
  "keywords": [
133
133
  "foldkit",