@parity-app/cli 0.0.0 → 0.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.
@@ -1,5 +1,5 @@
1
- import { S as lengthToPixels, a as applyLibraryEdits, c as isSampleElement, f as parseLibraryEdits, l as isSampleRender, m as renderSlotOf, p as parseLibraryManifest, s as isMadeValue, u as libraryManifestExtension } from "./src-CSeISXoZ.mjs";
2
- import "./src-uPmBVSsB.mjs";
1
+ import { S as lengthToPixels, a as applyLibraryEdits, c as isSampleElement, f as parseLibraryEdits, l as isSampleRender, m as renderSlotOf, p as parseLibraryManifest, s as isMadeValue, u as libraryManifestExtension } from "./src-D9EMN48r.mjs";
2
+ import "./src-DXZqtm6z.mjs";
3
3
  import { a as publishedVersions, n as packageFile, o as repositoryFiles, r as publishedSource } from "./published-CdXoUgfD.mjs";
4
4
  import { createRequire } from "node:module";
5
5
  import { mkdir, readFile, readdir, realpath, rm, stat, writeFile } from "node:fs/promises";
@@ -437,6 +437,10 @@ function parseJsonc(text) {
437
437
  }
438
438
  return JSON.parse(output.replace(/,(\s*[}\]])/g, "$1"));
439
439
  }
440
+ new Intl.Collator("en", {
441
+ numeric: true,
442
+ sensitivity: "base"
443
+ });
440
444
  // ../project/src/libraries.ts
441
445
  /**
442
446
  * Where a dependency is installed, found the way Node finds packages: in `node_modules` here or in a folder above. It
@@ -2923,14 +2927,39 @@ async function relateParts(load, specifier, components, providers = [], edits =
2923
2927
  if (!relation.parents || relation.inside || relation.visual === false) continue;
2924
2928
  if (!relation.parents.some((parent) => loose.has(parent))) continue;
2925
2929
  if (!asInserted(relation.parents, name, relation.sample?.children)) continue;
2930
+ const cleared = [];
2926
2931
  for (const parent of relation.parents) {
2927
2932
  const generated = loose.get(parent);
2928
2933
  const sample = relations.get(parent)?.sample;
2929
2934
  if (!generated || !sample) continue;
2930
2935
  loose.delete(parent);
2931
- if (Object.keys(generated).length > 0) sample.props = generated;
2936
+ const made = Object.entries(sample.props ?? {}).filter(([, value]) => isMadeValue(value) || Array.isArray(value) && value.some(isMadeValue));
2937
+ const kept = {
2938
+ ...generated,
2939
+ ...Object.fromEntries(made)
2940
+ };
2941
+ if (made.length > 0) cleared.push([
2942
+ parent,
2943
+ generated,
2944
+ kept
2945
+ ]);
2946
+ if (Object.keys(kept).length > 0) sample.props = kept;
2932
2947
  else delete sample.props;
2933
- if (!sample.props && !sample.children) delete relations.get(parent).sample;
2948
+ }
2949
+ if (cleared.length > 0) {
2950
+ const saved = cleared.map(([parent]) => [parent, samples.get(parent)]);
2951
+ for (const [parent, , kept] of cleared) samples.set(parent, kept);
2952
+ const fails = attempt(relation.parents, name, relation.sample?.children);
2953
+ for (const [parent, sample] of saved) samples.set(parent, sample ?? {});
2954
+ if (fails) for (const [parent, generated] of cleared) {
2955
+ const sample = relations.get(parent).sample;
2956
+ if (Object.keys(generated).length > 0) sample.props = generated;
2957
+ else delete sample.props;
2958
+ }
2959
+ }
2960
+ for (const parent of relation.parents) {
2961
+ const sample = relations.get(parent)?.sample;
2962
+ if (sample && !sample.props && !sample.children) delete relations.get(parent).sample;
2934
2963
  }
2935
2964
  }
2936
2965
  for (const [name, error] of Object.entries(appErrors)) {
@@ -2946,7 +2975,15 @@ async function relateParts(load, specifier, components, providers = [], edits =
2946
2975
  if (relation.parentsFrom === "edit") continue;
2947
2976
  const parents = relation.parents ?? [];
2948
2977
  const needed = named(error, name, parents, false);
2949
- if (!needed) continue;
2978
+ if (!needed) {
2979
+ const shown = exampleChain(name);
2980
+ if (shown && shown.join() !== parents.join() && !attempt(shown, name, relation.sample?.children)) {
2981
+ relation.parents = shown;
2982
+ relation.parentsFrom = "app";
2983
+ delete relation.optionalParents;
2984
+ }
2985
+ continue;
2986
+ }
2950
2987
  const outer = (relations.get(needed)?.parents ?? []).filter((parent) => parent !== name);
2951
2988
  relation.parents = namespaceOf(needed) === namespaceOf(name) ? [.../* @__PURE__ */ new Set([
2952
2989
  ...outer,
@@ -3012,6 +3049,46 @@ async function relateParts(load, specifier, components, providers = [], edits =
3012
3049
  delete relation.inside;
3013
3050
  }
3014
3051
  }
3052
+ const textOnly = /* @__PURE__ */ new Set();
3053
+ for (const [name, relation] of relations) {
3054
+ const texts = relation.sample?.children;
3055
+ if (!texts?.length || !texts.every((child) => typeof child === "string")) continue;
3056
+ const parents = relation.parents ?? [];
3057
+ if (!attempt(parents, name, [{
3058
+ component: "p",
3059
+ children: texts
3060
+ }]) || attempt(parents, name, texts)) continue;
3061
+ const { children: _, ...sample } = relation.sample;
3062
+ relation.sample = {
3063
+ ...sample,
3064
+ props: {
3065
+ ...sample.props,
3066
+ children: texts.join("")
3067
+ }
3068
+ };
3069
+ textOnly.add(name);
3070
+ }
3071
+ const asText = (children) => children.map((child) => {
3072
+ if (typeof child !== "object" || !("component" in child) || !child.children) return child;
3073
+ const { children: inner, ...node } = child;
3074
+ if (textOnly.has(child.component) && inner.length > 0 && inner.every((item) => typeof item === "string")) return {
3075
+ ...node,
3076
+ props: {
3077
+ ...node.props,
3078
+ children: inner.join("")
3079
+ }
3080
+ };
3081
+ return {
3082
+ ...node,
3083
+ children: asText(inner)
3084
+ };
3085
+ });
3086
+ if (textOnly.size > 0) {
3087
+ for (const relation of relations.values()) if (relation.sample?.children) relation.sample = {
3088
+ ...relation.sample,
3089
+ children: asText(relation.sample.children)
3090
+ };
3091
+ }
3015
3092
  for (const relation of relations.values()) {
3016
3093
  const nearest = relation.parents?.at(-1);
3017
3094
  if (nearest && relations.get(nearest)?.sample?.children?.length === 0 && relation.parentsFrom !== "edit") {
@@ -3567,6 +3644,11 @@ const presets = {
3567
3644
  return { tokens: [...tokens.values()] };
3568
3645
  }
3569
3646
  },
3647
+ recharts: {
3648
+ id: "recharts",
3649
+ name: "Recharts",
3650
+ description: "Charts, axes, series and grids to compose, as shadcn's charts are."
3651
+ },
3570
3652
  "lucide-react": {
3571
3653
  id: "lucide",
3572
3654
  name: "Lucide",
@@ -4614,8 +4696,16 @@ function exportsByName(file, name) {
4614
4696
  function loader(root, packageDir) {
4615
4697
  return async (specifier) => {
4616
4698
  for (const from of [root, packageDir]) {
4617
- const path = await resolveImport(from, specifier) ?? resolveRequire(from, specifier);
4618
- if (path) return await import(pathToFileURL(path).href);
4699
+ const esm = await resolveImport(from, specifier);
4700
+ const cjs = resolveRequire(from, specifier);
4701
+ const path = esm ?? cjs;
4702
+ if (!path) continue;
4703
+ try {
4704
+ return await import(pathToFileURL(path).href);
4705
+ } catch (error) {
4706
+ if (!cjs || cjs === path) throw error;
4707
+ return await import(pathToFileURL(cjs).href);
4708
+ }
4619
4709
  }
4620
4710
  throw new Error(`Can't find ${specifier} from ${root}`);
4621
4711
  };
@@ -1070,6 +1070,8 @@ function expectStringRecord(value, path) {
1070
1070
  return record;
1071
1071
  }
1072
1072
  // ../core/src/library-insert.ts
1073
+ /** Nodes whose `children` is the name `componentNode` gave them, rather than text someone set. */
1074
+ const named = /* @__PURE__ */ new WeakSet();
1073
1075
  /**
1074
1076
  * A new node for a component, ready to show something: required props get their default or first option, and a
1075
1077
  * component that takes children gets its own name as text, so it isn't an empty box.
@@ -1084,13 +1086,16 @@ function componentNode(component, info, taken, given = {}) {
1084
1086
  else if (prop.kind === "number") props[prop.name] = 0;
1085
1087
  else if (prop.kind === "string") props[prop.name] = prop.name;
1086
1088
  }
1087
- if (info?.props.some((prop) => prop.name === "children" && prop.kind === "node")) props.children = component.split("/").at(-1) ?? component;
1088
- return {
1089
+ const labelled = info?.props.some((prop) => prop.name === "children" && prop.kind === "node");
1090
+ if (labelled) props.children = component.split("/").at(-1) ?? component;
1091
+ const node = {
1089
1092
  type: "component",
1090
1093
  id: generateId(taken),
1091
1094
  component,
1092
1095
  ...Object.keys(props).length > 0 ? { props } : {}
1093
1096
  };
1097
+ if (labelled) named.add(node);
1098
+ return node;
1094
1099
  }
1095
1100
  /**
1096
1101
  * A library component as its library file says it's used: with its sample (a collection's items, an Accordion's
@@ -1164,9 +1169,11 @@ function withLibraryContext(node, sources, around, taken) {
1164
1169
  let placed = node;
1165
1170
  const sample = source.sample;
1166
1171
  if (sample) {
1172
+ const given = { ...node.props };
1173
+ if (sample.props && "children" in sample.props && named.has(node)) delete given.children;
1167
1174
  const { props, slots } = held({
1168
1175
  ...sample.props,
1169
- ...node.props
1176
+ ...given
1170
1177
  }, sample.children);
1171
1178
  if (sample.children) delete props.children;
1172
1179
  const { props: _label, ...rest } = node;
@@ -1251,6 +1258,7 @@ function librarySource(library, name, component, path, imported = (specifier) =>
1251
1258
  ...component.group ? { group: component.group } : {},
1252
1259
  ...component.parents ? { parents: component.parents.map((parent) => `${library}/${parent}`) } : {},
1253
1260
  ...component.internal ? { internal: true } : {},
1261
+ ...component.visual === false ? { visual: false } : {},
1254
1262
  ...component.optionalParents ? { optionalParents: component.optionalParents.map((parent) => `${library}/${parent}`) } : {},
1255
1263
  ...component.parentParts ? { parentParts: true } : {},
1256
1264
  ...component.sample ? { sample: sampleIds(component.sample, library, imported) } : {}
@@ -1,4 +1,4 @@
1
- import { p as parseLibraryManifest, u as libraryManifestExtension } from "./src-CSeISXoZ.mjs";
1
+ import { p as parseLibraryManifest, u as libraryManifestExtension } from "./src-D9EMN48r.mjs";
2
2
  import { createRequire } from "node:module";
3
3
  import { readFile, readdir } from "node:fs/promises";
4
4
  import { dirname, join } from "node:path";
@@ -1 +1 @@
1
- export { t as covers, n as registryDir, r as registryEntries } from "./src-uPmBVSsB.mjs";
1
+ export { t as covers, n as registryDir, r as registryEntries } from "./src-DXZqtm6z.mjs";
@@ -1,2 +1,2 @@
1
- export { a as applyLibraryEdits, t as componentNode, y as generateId, n as librarySource, f as parseLibraryEdits, i as withLibraryContext } from "./src-CSeISXoZ.mjs";
2
- import "./src-rlZNC2MU.mjs";
1
+ export { a as applyLibraryEdits, t as componentNode, y as generateId, n as librarySource, f as parseLibraryEdits, i as withLibraryContext } from "./src-D9EMN48r.mjs";
2
+ import "./src-8MhDV_sA.mjs";
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@parity-app/cli",
3
- "version": "0.0.0",
3
+ "version": "0.1.0",
4
4
  "license": "MIT",
5
5
  "type": "module",
6
6
  "description": "Drive the Parity app from a terminal or an agent: read state, run edits, take screenshots, serve MCP.",
@@ -120,6 +120,10 @@ type name a token from `GetTokens()`, without the `--`.
120
120
  | `transform`, `decoration`, `italic` | `uppercase` and the like, `underline` or `line-through`, `true` |
121
121
  | `lines` | Lines of text before an ellipsis |
122
122
 
123
+ A text layer sizes as Figma's text does, by its `width` and `height`: `width: "hug"` is auto width, one line as wide as
124
+ its text, wrapped only by a `maxWidth`; any other width, or none, with no `height` is auto height, wrapping at its width
125
+ and growing down; a `height` as well is fixed.
126
+
123
127
  Type set on a layout applies to the text inside it. A component's own look comes from its props, so reach for a variant
124
128
  (`variant: "secondary"`) before styling a component from outside.
125
129
 
package/skills/execute.md CHANGED
@@ -21,6 +21,8 @@ Get(path, { depth?, state? }?): Node // a design's root or a node; d
21
21
  Get(path?, visit): any[] // walks nodes, collecting what visit returns
22
22
  Components(): string[] // the components designs can use
23
23
  Props(component, { all? }?): PropsInfo // a component's props, from its source
24
+ Icons(): IconSet[] // the project's icon sets, with their styles
25
+ Icons(set, { search?, style?, limit? }): Icon[] // async: a set's icons, as component nodes name them
24
26
  GetTokens({ category?, source?, search? }?): Token[]
25
27
  GetModes(): { settings, modes } // the project's modes, and each resolved
26
28
  Selection(): { design?, node?, mode? } // what the person has selected
@@ -97,6 +99,26 @@ Print(Get((node, at) => (node.type === "component" && node.component === "Button
97
99
  source: variants with their options (`variant`, `size`), its own props, and with `{ all: true }` the attributes it
98
100
  passes to its element. A prop that isn't listed, or a variant value outside its options, comes back as a warning.
99
101
 
102
+ ### Icons
103
+
104
+ `Icons()` lists the project's icon sets: each one's `id`, `name`, `package`, `styles` (such as `outline` and `solid`,
105
+ empty when it has one) and the `style` used when none is asked for. An icon is a component node named `<set>/<Icon>`,
106
+ with no children. `await Icons("lucide", { search: "settings" })` finds icons by name, by the other names the set
107
+ exports them under and by the tags it publishes, best first; each comes back with its `label` and the `component` (and
108
+ `props`, for sets that take the style as a prop) to insert it with. Without `search` it lists the set's icons in order.
109
+ It returns 50 unless `limit` says otherwise, in the set's default style unless `style` names another.
110
+
111
+ ```js
112
+ // A settings button with the project's own settings icon.
113
+ const [icon] = await Icons(Icons()[0].id, { search: "settings", limit: 1 })
114
+ Insert("dashboard/Toolbar", {
115
+ type: "component",
116
+ component: "Button",
117
+ props: { variant: "ghost", "aria-label": "Settings" },
118
+ slots: { children: [{ type: "component", component: icon.component, props: icon.props }] }
119
+ })
120
+ ```
121
+
100
122
  ### GetTokens
101
123
 
102
124
  Each token has a `name`, a `category` (`color`, `font-size`, `radius`, `shadow`, `spacing`, `font`, `font-weight`,