eidotter 0.43.0 → 0.44.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 CHANGED
@@ -116,9 +116,9 @@ for client apps and `'use client'` files.
116
116
 
117
117
  ## Upgrading
118
118
 
119
- Every minor with breaking or visible changes ships an upgrade guide in the package, at `node_modules/eidotter/migrations/<version>.md` (source: [`migrations/`](./migrations/)). Read every guide between your installed version and the target, oldest first. Start with [0.41.0](./migrations/0.41.0.md), then [0.43.0](./migrations/0.43.0.md).
119
+ Every minor with breaking or visible changes ships an upgrade guide in the package, at `node_modules/eidotter/migrations/<version>.md` (source: [`migrations/`](./migrations/)). Read every guide between your installed version and the target, oldest first. Start with [0.41.0](./migrations/0.41.0.md), then [0.43.0](./migrations/0.43.0.md) and [0.44.0](./migrations/0.44.0.md).
120
120
 
121
- 0.x caret ranges stop at the next minor (`^0.40.2` never resolves to 0.41.0), so bump the range explicitly: `npm install eidotter@^0.43.0`.
121
+ 0.x caret ranges stop at the next minor (`^0.40.2` never resolves to 0.41.0), so bump the range explicitly: `npm install eidotter@^0.44.0`.
122
122
 
123
123
  ## Documentation
124
124
 
@@ -98,7 +98,12 @@ export const CmdPalette = forwardRef(({ open, onOpenChange, items, placeholder =
98
98
  useEffect(() => {
99
99
  setSelected(s => Math.min(s, Math.max(0, results.length - 1)));
100
100
  }, [results.length]);
101
- // Focus input when open (React Aria handles focus trap; we steer to input)
101
+ // Focus the input when the palette opens. `autoFocus` on the input focuses
102
+ // it during the commit of the opening click or keypress, which is what
103
+ // mobile Safari needs to raise the on-screen keyboard (a focus() call in a
104
+ // later timer is outside the user gesture, so iOS focuses without a
105
+ // keyboard). This timer is the fallback for environments where the dialog's
106
+ // own focus management lands after the mount.
102
107
  useEffect(() => {
103
108
  if (open) {
104
109
  const id = window.setTimeout(() => inputRef.current?.focus(), 10);
@@ -162,9 +167,8 @@ export const CmdPalette = forwardRef(({ open, onOpenChange, items, placeholder =
162
167
  };
163
168
  return (_jsxs(DosDialog, { ref: ref, open: open, onOpenChange: onOpenChange, placement: "top", size: "lg", "aria-label": ariaLabel, className: cn('eidotter-cmdpal__container', className), head: {
164
169
  title: 'JUMP TO',
165
- end: _jsx("span", { className: "eidotter-cmdpal__blink", children: "_" }),
166
170
  decorative: true,
167
- }, footer: footerHint ? (_jsx("div", { className: "eidotter-cmdpal__footer", "aria-hidden": "true", children: footerHint })) : undefined, children: [_jsx("input", { ref: inputRef, type: "text", role: "combobox", "aria-controls": listboxId, "aria-expanded": true, "aria-autocomplete": "list", "aria-activedescendant": results[selected] ? `${baseId}-item-${results[selected].id}` : undefined, className: "eidotter-cmdpal__input", value: query, placeholder: placeholder, onChange: e => setQuery(e.target.value), onKeyDown: handleKeyDown }), _jsxs("ul", { ref: listRef, id: listboxId, role: "listbox", "aria-label": ariaLabel, className: "eidotter-cmdpal__results", children: [results.length === 0 && (_jsx("li", { className: "eidotter-cmdpal__empty", role: "presentation", children: emptyMessage })), results.map((item, i) => {
171
+ }, footer: footerHint ? (_jsx("div", { className: "eidotter-cmdpal__footer", "aria-hidden": "true", children: footerHint })) : undefined, children: [_jsx("input", { ref: inputRef, autoFocus: true, type: "text", enterKeyHint: "go", autoComplete: "off", autoCorrect: "off", autoCapitalize: "off", spellCheck: false, role: "combobox", "aria-controls": listboxId, "aria-expanded": true, "aria-autocomplete": "list", "aria-activedescendant": results[selected] ? `${baseId}-item-${results[selected].id}` : undefined, className: "eidotter-cmdpal__input", value: query, placeholder: placeholder, onChange: e => setQuery(e.target.value), onKeyDown: handleKeyDown }), _jsxs("ul", { ref: listRef, id: listboxId, role: "listbox", "aria-label": ariaLabel, className: "eidotter-cmdpal__results", children: [results.length === 0 && (_jsx("li", { className: "eidotter-cmdpal__empty", role: "presentation", children: emptyMessage })), results.map((item, i) => {
168
172
  const isSelected = i === selected;
169
173
  return (_jsx("li", { id: `${baseId}-item-${item.id}`, role: "option", "aria-selected": isSelected, "data-index": i, className: cn('eidotter-cmdpal__item', isSelected && 'eidotter-cmdpal__item--selected'), onMouseMove: () => {
170
174
  if (suppressHoverRef.current)
@@ -1,20 +1,20 @@
1
1
  import React, { FC } from 'react';
2
2
  type PixelIcon = FC<React.SVGProps<SVGSVGElement>>;
3
3
  declare const ICON_MAP: {
4
- Info: (props: React.SVGProps<SVGSVGElement>) => JSX.Element;
5
- Warning: (props: React.SVGProps<SVGSVGElement>) => JSX.Element;
6
- Error: (props: React.SVGProps<SVGSVGElement>) => JSX.Element;
7
- Done: (props: React.SVGProps<SVGSVGElement>) => JSX.Element;
8
- Check: (props: React.SVGProps<SVGSVGElement>) => JSX.Element;
4
+ Info: (props: React.SVGProps<SVGSVGElement>) => React.JSX.Element;
5
+ Warning: (props: React.SVGProps<SVGSVGElement>) => React.JSX.Element;
6
+ Error: (props: React.SVGProps<SVGSVGElement>) => React.JSX.Element;
7
+ Done: (props: React.SVGProps<SVGSVGElement>) => React.JSX.Element;
8
+ Check: (props: React.SVGProps<SVGSVGElement>) => React.JSX.Element;
9
9
  Close: PixelIcon;
10
- 'Chevron Up': (props: React.SVGProps<SVGSVGElement>) => JSX.Element;
11
- 'Chevron Down': (props: React.SVGProps<SVGSVGElement>) => JSX.Element;
12
- 'Chevron Left': (props: React.SVGProps<SVGSVGElement>) => JSX.Element;
13
- 'Chevron Right': (props: React.SVGProps<SVGSVGElement>) => JSX.Element;
14
- App: (props: React.SVGProps<SVGSVGElement>) => JSX.Element;
15
- Cancel: (props: React.SVGProps<SVGSVGElement>) => JSX.Element;
16
- Fullscreen: (props: React.SVGProps<SVGSVGElement>) => JSX.Element;
17
- Add: (props: React.SVGProps<SVGSVGElement>) => JSX.Element;
10
+ 'Chevron Up': (props: React.SVGProps<SVGSVGElement>) => React.JSX.Element;
11
+ 'Chevron Down': (props: React.SVGProps<SVGSVGElement>) => React.JSX.Element;
12
+ 'Chevron Left': (props: React.SVGProps<SVGSVGElement>) => React.JSX.Element;
13
+ 'Chevron Right': (props: React.SVGProps<SVGSVGElement>) => React.JSX.Element;
14
+ App: (props: React.SVGProps<SVGSVGElement>) => React.JSX.Element;
15
+ Cancel: (props: React.SVGProps<SVGSVGElement>) => React.JSX.Element;
16
+ Fullscreen: (props: React.SVGProps<SVGSVGElement>) => React.JSX.Element;
17
+ Add: (props: React.SVGProps<SVGSVGElement>) => React.JSX.Element;
18
18
  };
19
19
  export type IconName = keyof typeof ICON_MAP;
20
20
  /**
@@ -1,17 +1,17 @@
1
1
  'use client';
2
2
  import { jsx as _jsx } from "react/jsx-runtime";
3
- import { InfoBox } from 'pixelarticons/react/InfoBox';
4
- import { WarningDiamond } from 'pixelarticons/react/WarningDiamond';
5
- import { SquareAlert } from 'pixelarticons/react/SquareAlert';
6
- import { Check } from 'pixelarticons/react/Check';
7
- import { ChevronUp } from 'pixelarticons/react/ChevronUp';
8
- import { ChevronDown } from 'pixelarticons/react/ChevronDown';
9
- import { ChevronLeft } from 'pixelarticons/react/ChevronLeft';
10
- import { ChevronRight } from 'pixelarticons/react/ChevronRight';
11
- import { WindowFrame } from 'pixelarticons/react/WindowFrame';
12
- import { Minus } from 'pixelarticons/react/Minus';
13
- import { Expand } from 'pixelarticons/react/Expand';
14
- import { Plus } from 'pixelarticons/react/Plus';
3
+ import { InfoBox } from 'pixelarticons/react/InfoBox.js';
4
+ import { WarningDiamond } from 'pixelarticons/react/WarningDiamond.js';
5
+ import { SquareAlert } from 'pixelarticons/react/SquareAlert.js';
6
+ import { Check } from 'pixelarticons/react/Check.js';
7
+ import { ChevronUp } from 'pixelarticons/react/ChevronUp.js';
8
+ import { ChevronDown } from 'pixelarticons/react/ChevronDown.js';
9
+ import { ChevronLeft } from 'pixelarticons/react/ChevronLeft.js';
10
+ import { ChevronRight } from 'pixelarticons/react/ChevronRight.js';
11
+ import { WindowFrame } from 'pixelarticons/react/WindowFrame.js';
12
+ import { Minus } from 'pixelarticons/react/Minus.js';
13
+ import { Expand } from 'pixelarticons/react/Expand.js';
14
+ import { Plus } from 'pixelarticons/react/Plus.js';
15
15
  import { cn } from '../../../utils/cn.js';
16
16
  /**
17
17
  * Custom pixel-art X mark — pixelarticons v2 has no standalone close/X glyph.
@@ -16,6 +16,13 @@ export interface LegalPageProps {
16
16
  home?: React.ReactNode;
17
17
  /** Body content — `<h2>`, `<p>`, `<ul>`, `<address>` children styled by the wrapper. */
18
18
  children: React.ReactNode;
19
+ /**
20
+ * Render inside the site's own page column (e.g. `PageShell`) instead of
21
+ * as a standalone page: no own 720px column, centring, padding, background
22
+ * or font, and a start-aligned hero without the rule under it. The type
23
+ * scale and body styles stay. Default `false`.
24
+ */
25
+ embedded?: boolean;
19
26
  /** Extra class on the outer wrapper */
20
27
  className?: string;
21
28
  }
@@ -8,4 +8,4 @@ import { cn } from '../../../utils/cn.js';
8
8
  * `<h2>`/`<p>`/`<ul>` body content (or pre-built clauses from this module)
9
9
  * and the wrapper handles spacing, type scale, and the `>` list bullet.
10
10
  */
11
- export const LegalPage = ({ title, date, intro, home, children, className, ...props }) => (_jsxs("div", { className: cn('eidotter-legal-page', className), ...props, children: [home && _jsx("div", { className: "eidotter-legal-page__home", children: home }), _jsxs("article", { children: [_jsxs("header", { className: "eidotter-legal-page__hero", children: [_jsx("p", { className: "eidotter-legal-page__date", children: date }), _jsx("h1", { children: title }), intro && _jsx("div", { className: "eidotter-legal-page__intro", children: intro })] }), _jsx("div", { className: "eidotter-legal-page__body", children: children })] })] }));
11
+ export const LegalPage = ({ title, date, intro, home, embedded = false, children, className, ...props }) => (_jsxs("div", { className: cn('eidotter-legal-page', embedded && 'eidotter-legal-page--embedded', className), ...props, children: [home && _jsx("div", { className: "eidotter-legal-page__home", children: home }), _jsxs("article", { children: [_jsxs("header", { className: "eidotter-legal-page__hero", children: [_jsx("p", { className: "eidotter-legal-page__date", children: date }), _jsx("h1", { children: title }), intro && _jsx("div", { className: "eidotter-legal-page__intro", children: intro })] }), _jsx("div", { className: "eidotter-legal-page__body", children: children })] })] }));
@@ -38,7 +38,10 @@ export interface PageShellProps extends React.HTMLAttributes<HTMLDivElement> {
38
38
  * `<main>`.
39
39
  */
40
40
  contentAs?: 'main' | 'div';
41
- /** `id` for the content element, e.g. a Header `skipLinkTarget` (`#content`). */
41
+ /**
42
+ * `id` for the content element, e.g. a Header `skipLinkTarget` (`#content`).
43
+ * Also sets `tabIndex={-1}`, so following the skip link moves focus there.
44
+ */
42
45
  contentId?: string;
43
46
  /** Page sections (`PageSection`, Bench, …), stacked with a 40px gap. */
44
47
  children?: React.ReactNode;
@@ -53,6 +56,10 @@ export interface PageShellProps extends React.HTMLAttributes<HTMLDivElement> {
53
56
  * with a 40px gap. No dividers: the only lines on the page are the ones its
54
57
  * children draw (window frames, pane gaps).
55
58
  *
59
+ * Paints no background and sets no font: the page's own ground (a CRT tint,
60
+ * RetroEffects) and body font show through. Pass a `className` to paint
61
+ * an opaque ground.
62
+ *
56
63
  * Server-safe and presentational. Ref forwards to the root `<div>`.
57
64
  */
58
65
  export declare const PageShell: React.ForwardRefExoticComponent<PageShellProps & React.RefAttributes<HTMLDivElement>>;
@@ -16,6 +16,10 @@ function PageIntro({ intro }) {
16
16
  * with a 40px gap. No dividers: the only lines on the page are the ones its
17
17
  * children draw (window frames, pane gaps).
18
18
  *
19
+ * Paints no background and sets no font: the page's own ground (a CRT tint,
20
+ * RetroEffects) and body font show through. Pass a `className` to paint
21
+ * an opaque ground.
22
+ *
19
23
  * Server-safe and presentational. Ref forwards to the root `<div>`.
20
24
  */
21
25
  export const PageShell = forwardRef(({ header, intro, footer, maxWidth, contentAs = 'main', contentId, children, className, style, ...rest }, ref) => {
@@ -24,6 +28,6 @@ export const PageShell = forwardRef(({ header, intro, footer, maxWidth, contentA
24
28
  const mergedStyle = width
25
29
  ? { ...style, '--eidotter-page-shell-max': width }
26
30
  : style;
27
- return (_jsx("div", { ref: ref, className: cn('eidotter-page-shell', className), style: mergedStyle, ...rest, children: _jsxs("div", { className: "eidotter-page-shell__column", children: [header != null && header !== false && (_jsx("div", { className: "eidotter-page-shell__header", children: header })), _jsxs(Content, { id: contentId, className: "eidotter-page-shell__content", children: [intro && _jsx(PageIntro, { intro: intro }), children] }), footer != null && footer !== false && (_jsx("div", { className: "eidotter-page-shell__footer", children: footer }))] }) }));
31
+ return (_jsx("div", { ref: ref, className: cn('eidotter-page-shell', className), style: mergedStyle, ...rest, children: _jsxs("div", { className: "eidotter-page-shell__column", children: [header != null && header !== false && (_jsx("div", { className: "eidotter-page-shell__header", children: header })), _jsxs(Content, { id: contentId, tabIndex: contentId ? -1 : undefined, className: "eidotter-page-shell__content", children: [intro && _jsx(PageIntro, { intro: intro }), children] }), footer != null && footer !== false && (_jsx("div", { className: "eidotter-page-shell__footer", children: footer }))] }) }));
28
32
  });
29
33
  PageShell.displayName = 'PageShell';