@lotics/ui 12.0.0 → 12.1.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/AGENTS.md CHANGED
@@ -34,7 +34,7 @@ doc before building any screen, **never from memory**. Exact props are the shipp
34
34
 
35
35
  | Doc | Read it for |
36
36
  |---|---|
37
- | [docs/catalog.md](./docs/catalog.md) | **The complete inventory** — Reach-by-role (each data role → the ONE canonical component) + every `@lotics/ui/<module>` entry point. Read before building any screen; reuse first. |
37
+ | [docs/catalog.md](./docs/catalog.md) | **The complete inventory** — Reach-by-role (each data role → the ONE canonical component) + every `@lotics/ui/<module>` entry point (incl. `@lotics/ui/vite`'s `loticsOptimizeDeps` for a custom-code app's `vite.config.ts`). Read before building any screen; reuse first. |
38
38
  | [docs/data_entry.md](./docs/data_entry.md) | Which editing pattern for which job — inline edit, fieldset forms, find-or-create (`Combobox`), line items, handoffs, phased records, billing, tags, dispositions, attachments, stage gates. |
39
39
  | [docs/ai_patterns.md](./docs/ai_patterns.md) | AI proposes, the human decides — composer, live run feed (`AgentRun`), review-before-apply, findings, provenance, confidence; the UI half of the SDK's [ai doc](../app-sdk/docs/ai.md). |
40
40
  | [docs/composition.md](./docs/composition.md) | The design-language contract — canvas + content column, heading altitude, banded cards, register vs inset rows, master-detail `Drawer`, view controls, color discipline, typography, whitespace. |
package/docs/catalog.md CHANGED
@@ -263,6 +263,17 @@ verdict the host records; `finding` locale slice).
263
263
  Every published entry point, grouped by area. Import as `@lotics/ui/<module>`; the module's
264
264
  source (`src/<module>.tsx`/`.ts`) is the API reference.
265
265
 
266
+ ### Dev / build integration
267
+
268
+ - **`vite`** — `loticsOptimizeDeps`: the canonical `optimizeDeps.include` list a custom-code
269
+ app's `vite.config.ts` must pre-bundle for `lotics app dev` to render (RN-ecosystem + markdown
270
+ CJS-interop; dev-only — the prod rollup build resolves the interop without it). Ships WITH the
271
+ kit so it can never drift from what @lotics/ui's transitive deps require across a major bump —
272
+ the scaffold's `vite.config.ts` imports it instead of hardcoding the list:
273
+ `import { loticsOptimizeDeps } from "@lotics/ui/vite"` → `optimizeDeps: { include: loticsOptimizeDeps }`.
274
+ To add app-specific entries, spread: `include: [...loticsOptimizeDeps, "my-dep"]`. A Node-loadable
275
+ `.mjs` leaf (a Vite config can't import a `.ts` from `node_modules`), zero-import by contract.
276
+
266
277
  ### Text & formatting
267
278
 
268
279
  - **`text`** — the `Text` primitive (never raw `div`/`span`/`fontSize`): `size` `xs`–`xxxl`
package/package.json CHANGED
@@ -1,8 +1,12 @@
1
1
  {
2
2
  "name": "@lotics/ui",
3
- "version": "12.0.0",
3
+ "version": "12.1.0",
4
4
  "type": "module",
5
5
  "exports": {
6
+ "./vite": {
7
+ "types": "./src/vite.d.mts",
8
+ "default": "./src/vite.mjs"
9
+ },
6
10
  "./tokens": "./src/tokens.ts",
7
11
  "./colors": "./src/colors.ts",
8
12
  "./option_badge": "./src/option_badge.tsx",
package/src/vite.d.mts ADDED
@@ -0,0 +1,7 @@
1
+ /**
2
+ * Types for the `@lotics/ui/vite` subpath (runtime lives in `vite.mjs`).
3
+ *
4
+ * `readonly` so a consumer can't mutate the shared canonical list; spread it to
5
+ * extend: `include: [...loticsOptimizeDeps, "my-extra-dep"]`.
6
+ */
7
+ export declare const loticsOptimizeDeps: readonly string[];
package/src/vite.mjs ADDED
@@ -0,0 +1,67 @@
1
+ /**
2
+ * Vite dev-optimizer config for Lotics custom-code apps — the `@lotics/ui/vite` subpath.
3
+ *
4
+ * ZERO-IMPORT LEAF. This module is loaded inside Vite's Node config context
5
+ * (a scaffolded app's `vite.config.ts` imports it), so it must pull in NOTHING —
6
+ * no react-native-web, no kit components, no other module. It exports only a
7
+ * plain array of strings. It ships as `.mjs` (not `.ts`) on purpose: a Vite
8
+ * config bundle externalizes its bare imports to their on-disk paths and hands
9
+ * them to Node's `import()`, and Node refuses to strip types for a `.ts` file
10
+ * under `node_modules` — a source `.ts` export would fail the config load.
11
+ *
12
+ * `loticsOptimizeDeps` is the set of module specifiers a scaffolded app's
13
+ * `vite.config.ts` `optimizeDeps.include` MUST carry for `lotics app dev` to
14
+ * render. Vite's dev dep-optimizer pre-bundles these to synthesize the
15
+ * CJS-interop (`default` / named) exports the RN-ecosystem + markdown subtree
16
+ * ship un-prebundled — otherwise one of them blanks the dev iframe with "does
17
+ * not provide an export named 'default'/'parse'". Dev-ONLY: the production
18
+ * rollup build resolves the interop without it (typecheck/lint/build stay green
19
+ * while the dev iframe goes blank), which is exactly why this list ships WITH
20
+ * the kit — so it can never drift from what @lotics/ui's transitive deps
21
+ * require across a major bump.
22
+ *
23
+ * Why each family is here:
24
+ * - `react-native-svg` — @lotics/ui's svg charts (PieChart/LineChart/Sparkline/
25
+ * RingGauge) reach a named-export entry the dev optimizer won't resolve
26
+ * unbundled ("does not provide an export named 'parse'").
27
+ * - `react-native-web` + `@react-native/normalize-colors` + the `inline-style-
28
+ * prefixer` / `fbjs` / `styleq` / `postcss-value-parser` / `nullthrows` core —
29
+ * RN-Web's CJS deps; force-prebundling folds them into interop'd chunks, and
30
+ * the deep subpaths it reaches via *default* imports need an ESM shim.
31
+ * - `react-markdown` — @lotics/ui's Markdown renderer (AgentRun + any markdown
32
+ * surface) pulls a transitive CJS dep (`style-to-js`) whose default export the
33
+ * dev optimizer won't synthesize unbundled.
34
+ * - `react` / `react-dom` / `react-dom/client` — pinned into the pre-bundle so
35
+ * every kit subpath shares one React instance (else "Invalid hook call").
36
+ *
37
+ * Usage — consumed by a scaffolded app's `vite.config.ts`:
38
+ *
39
+ * import { loticsOptimizeDeps } from "@lotics/ui/vite";
40
+ * export default defineConfig({ optimizeDeps: { include: loticsOptimizeDeps } });
41
+ *
42
+ * To add app-specific pre-bundle entries, spread the list:
43
+ *
44
+ * optimizeDeps: { include: [...loticsOptimizeDeps, "my-extra-dep"] }
45
+ */
46
+ export const loticsOptimizeDeps = [
47
+ "react-native-svg",
48
+ "react-markdown",
49
+ "react-native-web",
50
+ "@react-native/normalize-colors",
51
+ "inline-style-prefixer/lib/createPrefixer",
52
+ "inline-style-prefixer/lib/plugins/crossFade",
53
+ "inline-style-prefixer/lib/plugins/imageSet",
54
+ "inline-style-prefixer/lib/plugins/logical",
55
+ "inline-style-prefixer/lib/plugins/position",
56
+ "inline-style-prefixer/lib/plugins/sizing",
57
+ "inline-style-prefixer/lib/plugins/transition",
58
+ "postcss-value-parser",
59
+ "fbjs/lib/invariant",
60
+ "fbjs/lib/warning",
61
+ "styleq",
62
+ "styleq/transform-localize-style",
63
+ "react",
64
+ "react-dom",
65
+ "react-dom/client",
66
+ "nullthrows",
67
+ ];
@@ -0,0 +1,41 @@
1
+ import { describe, it, expect } from "vitest";
2
+ import * as fs from "node:fs";
3
+ import * as path from "node:path";
4
+ import { loticsOptimizeDeps } from "./vite.mjs";
5
+
6
+ describe("@lotics/ui/vite", () => {
7
+ it("exports a non-empty list of module-specifier strings", () => {
8
+ expect(Array.isArray(loticsOptimizeDeps)).toBe(true);
9
+ expect(loticsOptimizeDeps.length).toBeGreaterThan(0);
10
+ for (const entry of loticsOptimizeDeps) {
11
+ expect(typeof entry).toBe("string");
12
+ expect(entry.length).toBeGreaterThan(0);
13
+ }
14
+ });
15
+
16
+ it("is a zero-import leaf (it loads inside Vite's Node config context)", () => {
17
+ // The module is imported by an app's `vite.config.ts`, evaluated by Node
18
+ // before any resolve.alias or RN-Web shim exists. A single import would drag
19
+ // react-native-web (and its Metro globals) into the Node config load and
20
+ // crash it — so the runtime module must import nothing at all. Strip comments
21
+ // first so the usage example in the header (which shows an `import` line) is
22
+ // not mistaken for real code.
23
+ const raw = fs.readFileSync(path.join(__dirname, "vite.mjs"), "utf-8");
24
+ const code = raw
25
+ .replace(/\/\*[\s\S]*?\*\//g, "")
26
+ .replace(/(^|[^:])\/\/.*$/gm, "$1");
27
+ expect(code).not.toMatch(/^\s*import\b/m);
28
+ expect(code).not.toMatch(/\bfrom\s+["']/);
29
+ expect(code).not.toMatch(/\brequire\s*\(/);
30
+ });
31
+
32
+ test("carries the load-bearing RN-Web interop entries (a missing one blanks the dev iframe)", () => {
33
+ // RN-Web does `import normalizeColor from "@react-native/normalize-colors"`
34
+ // (nested CJS): un-prebundled, the dev server serves it as ESM with no
35
+ // default export and the iframe blanks the moment a colour-touching
36
+ // component mounts. These membership pins port the scaffold-era literal
37
+ // assertions to the list's owner.
38
+ expect(loticsOptimizeDeps).toContain("react-native-web");
39
+ expect(loticsOptimizeDeps).toContain("@react-native/normalize-colors");
40
+ });
41
+ });