@webority/canvas-kit 0.0.0-stage → 0.83.6
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/LICENSE +5 -0
- package/README.md +66 -2
- package/dist/browser.js +1 -0
- package/dist/build.js +3 -0
- package/dist/cli.js +5 -0
- package/dist/declarations.js +1 -0
- package/dist/files.js +1 -0
- package/dist/index.js +1 -0
- package/dist/kitModule.js +1 -0
- package/dist/manifest.js +1 -0
- package/dist/phone.js +1 -0
- package/dist/release.js +1 -0
- package/dist/releaseStamp.js +1 -0
- package/dist/spec.d.ts +33 -0
- package/dist/styleKeyTable.js +1 -0
- package/dist/tokens.js +1 -0
- package/package.json +29 -3
package/LICENSE
ADDED
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
Copyright (c) Webority Technologies. All rights reserved.
|
|
2
|
+
|
|
3
|
+
This software and its source code are proprietary and confidential to
|
|
4
|
+
Webority Technologies. Use is restricted to Webority products and teams under
|
|
5
|
+
internal license. Redistribution outside Webority Technologies is prohibited.
|
package/README.md
CHANGED
|
@@ -1,3 +1,67 @@
|
|
|
1
|
-
#
|
|
1
|
+
# @webority/canvas-kit
|
|
2
2
|
|
|
3
|
-
|
|
3
|
+
Builds a product's kit for Webority Canvas. A kit is the product's pinned Webority library plus its own presentational
|
|
4
|
+
components. The build writes an immutable release folder that Canvas stores and draws screens with.
|
|
5
|
+
|
|
6
|
+
## Build a release
|
|
7
|
+
|
|
8
|
+
```sh
|
|
9
|
+
canvas-kit build --config canvas-kit.json --out canvas-kit-release
|
|
10
|
+
```
|
|
11
|
+
|
|
12
|
+
`--out` must not exist. A release folder is never overwritten; build into a new folder.
|
|
13
|
+
|
|
14
|
+
The config is a JSON object with these keys. Paths are relative to the config file.
|
|
15
|
+
|
|
16
|
+
| Key | Meaning |
|
|
17
|
+
| --- | --- |
|
|
18
|
+
| `kit` | The kit key, lowercase letters, digits and hyphens, 2 to 40 characters, for example `lumex-portal`. |
|
|
19
|
+
| `platform` | `Web` or `Phone`. A Web kit takes its tokens from the theme and its icons from the library; a Phone kit takes both from the phone library. |
|
|
20
|
+
| `entry` | The kit's entry module, which exports the components. |
|
|
21
|
+
| `libraryPackage` | The Webority library the product pins, for example `@webority/ui-react`. |
|
|
22
|
+
| `rolesFile` | Optional. A JSON object from component name to `title` or `navigation`. |
|
|
23
|
+
| `rendererProtocolVersion` | The renderer protocol number the kit is built for. |
|
|
24
|
+
| `phoneStyleSupportFile` | The phone renderer's support file. It gives each style key a `phoneSupported` flag, and every style key must be listed as a boolean. |
|
|
25
|
+
|
|
26
|
+
## What a release holds
|
|
27
|
+
|
|
28
|
+
- `kit.js`: one ES module whose default export comes from `defineKit`. React and react-dom stay bare imports, so the renderer's own React draws the kit. A Phone kit also leaves react-native and react-native-svg bare; the phone renderer's import map resolves them.
|
|
29
|
+
- `kit.css`: the styles the bundle imports, or an empty file.
|
|
30
|
+
- `manifest.json`: the components with their props, sources and roles, the library's tokens and icons, and the style keys, each with its `phoneSupported` flag.
|
|
31
|
+
- `release.json`: the kit key, the product version, the kit module version, the protocol version, the library version, and the SHA-256 and byte count of each file above.
|
|
32
|
+
|
|
33
|
+
## Product components
|
|
34
|
+
|
|
35
|
+
A kit component is an exported function declaration whose props are typed in JSDoc, for example
|
|
36
|
+
`@param {SampleBadgeProps} props` with a `@typedef` beside it. The build runs the TypeScript compiler over the entry to
|
|
37
|
+
read those types. Components of the library come from the library's own declaration files.
|
|
38
|
+
|
|
39
|
+
## Refusals
|
|
40
|
+
|
|
41
|
+
The build stops with a named fix when:
|
|
42
|
+
|
|
43
|
+
- the kit imports `react-redux`, `react-router-dom`, `axios`, or a file under `src/services`;
|
|
44
|
+
- the product's React is not major 19, the Canvas renderer's React major;
|
|
45
|
+
- the library installed differs from the exact version the product pins;
|
|
46
|
+
- a role names a component the kit does not have, or a role is not `title` or `navigation`;
|
|
47
|
+
- a product component takes a name the library already exports.
|
|
48
|
+
|
|
49
|
+
## Reading a release back
|
|
50
|
+
|
|
51
|
+
`readReleaseManifest(dir)` checks every stamped file against `release.json` and returns the stamp and the manifest.
|
|
52
|
+
Any file changed after the build fails the check.
|
|
53
|
+
|
|
54
|
+
## Exports
|
|
55
|
+
|
|
56
|
+
- `.`: `kitModuleVersion`, `KIT_MODULE_EXTERNALS`, `defineKit`, `readManifest`, `readReleaseManifest(dir)`, `buildKitRelease`, `readConfig`. Node only.
|
|
57
|
+
- `./kitModule`: the kit module contract alone.
|
|
58
|
+
- `./browser`: for the renderers, with no Node built-ins. `readReleaseManifest({ release, files })` checks the bytes the board sent against the stamp and returns the manifest. `loadKitModule({ release, script })` imports the bundle through a blob address and refuses a kit module version it does not read.
|
|
59
|
+
|
|
60
|
+
## Tests
|
|
61
|
+
|
|
62
|
+
The package builds into `dist` before publish: `pnpm run build`. Its tests run with `pnpm test`, which reads the
|
|
63
|
+
source under `src`. The tests build throwaway product folders with a stub library, so they need only the
|
|
64
|
+
package's own dependencies installed.
|
|
65
|
+
|
|
66
|
+
The sample kit under `src/__fixtures__/sample-kit` resolves `@webority/ui-react` and `react` through this package's
|
|
67
|
+
devDependencies, so it builds from the workspace after `pnpm install`.
|
package/dist/browser.js
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
import"./kitModule.js";import{changedMessage as e,checkStampFiles as t}from"./releaseStamp.js";function n(e){if(typeof e==`string`)return new TextEncoder().encode(e);if(e instanceof ArrayBuffer)return new Uint8Array(e);if(ArrayBuffer.isView(e))return new Uint8Array(e.buffer,e.byteOffset,e.byteLength);throw Error(`A release file must be text, an ArrayBuffer or a typed array.`)}async function r(e){let t=await globalThis.crypto.subtle.digest(`SHA-256`,e);return Array.from(new Uint8Array(t),e=>e.toString(16).padStart(2,`0`)).join(``)}async function i({release:i,files:a={}}){t(i,`the release ${i?.name}`);let o={};for(let[t,s]of Object.entries(i.files)){if(!Object.hasOwn(a,t))throw Error(`${t} is missing from the release ${i.name}.`);let c=n(a[t]);if(await r(c)!==s.sha256||c.byteLength!==s.bytes)throw Error(e(t,`the release ${i.name}`));o[t]=c}return{release:i,manifest:JSON.parse(new TextDecoder().decode(o[`manifest.json`]))}}async function a(e){let t=URL.createObjectURL(new Blob([e],{type:`text/javascript`}));try{return await import(t)}finally{URL.revokeObjectURL(t)}}async function o({release:e,script:t,importScript:r=a}){if(e?.kitModuleVersion!==1)throw Error(`Release ${e?.name} was built for kit module version ${e?.kitModuleVersion}; this renderer reads version 1. Rebuild the release with the @webority/canvas-kit that reads version 1.`);let i=(await r(new TextDecoder().decode(n(t))))?.default;if(i?.kitModuleVersion!==1)throw Error(`The kit bundle of release ${e.name} declares kit module version ${i?.kitModuleVersion}; this renderer reads version 1. Rebuild the release.`);return i}export{o as loadKitModule,i as readReleaseManifest};
|
package/dist/build.js
ADDED
|
@@ -0,0 +1,3 @@
|
|
|
1
|
+
import{findPackageDir as e,readJson as t,toPosix as n}from"./files.js";import{KIT_MODULE_EXTERNALS as r}from"./kitModule.js";import{libraryFiles as i,readManifest as a}from"./manifest.js";import{digest as o,writeReleaseFolder as s}from"./release.js";import{existsSync as c}from"node:fs";import{dirname as l,join as u,resolve as d}from"node:path";import{fileURLToPath as f}from"node:url";import{build as p}from"vite";var m=19,h=[`react-redux`,`react-router-dom`,`axios`],g=[`kit`,`platform`,`entry`,`libraryPackage`,`rolesFile`,`rendererProtocolVersion`,`phoneStyleSupportFile`],_=[`kit`,`platform`,`entry`,`libraryPackage`,`rendererProtocolVersion`,`phoneStyleSupportFile`],v=`canvas-kit:entry`,y=`\0${v}`,b=u(l(f(import.meta.url)),`kitModule.js`);function x(e){let n=t(e);if(typeof n!=`object`||!n||Array.isArray(n))throw Error(`${e} must be a JSON object.`);for(let t of Object.keys(n))if(!g.includes(t))throw Error(`${e} has the unknown key ${t}. The keys are ${g.join(`, `)}.`);for(let t of _)if(n[t]===void 0)throw Error(`${e} needs the key ${t}.`);for(let t of[`kit`,`platform`,`entry`,`libraryPackage`,`phoneStyleSupportFile`])if(typeof n[t]!=`string`)throw Error(`${e}: ${t} must be a string.`);if(n.rolesFile!==void 0&&typeof n.rolesFile!=`string`)throw Error(`${e}: rolesFile must be a string path.`);return n}function S(n){let r=e(n,`react`);if(!r)throw Error(`react is not installed for ${n}. Run pnpm install there.`);let{version:i}=t(u(r,`package.json`));if(Number(String(i).split(`.`)[0])!==m)throw Error(`The product uses React ${i}; the Canvas renderer runs React ${m}. Pin react to ${m}.x and rebuild.`)}function C({kit:e,platform:t,entryFile:r,libraryFile:i,libraryNames:a,productNames:o}){let s=[`import { defineKit } from ${JSON.stringify(n(b))};`,`import * as product from ${JSON.stringify(n(r))};`];a.length>0&&s.push(`import { ${a.join(`, `)} } from ${JSON.stringify(n(i))};`);let c=[...a,...o.map(e=>`${e}: product.${e}`)];return s.push(`export default defineKit({ kit: ${JSON.stringify(e)}, platform: ${JSON.stringify(t)}, componentMap: { ${c.join(`, `)} } });`,``),s.join(`
|
|
2
|
+
`)}function w(e){return{name:`canvas-kit-entry`,resolveId(e){return e===v?y:null},load(t){return t===y?e:null}}}function T(e){let t=`${n(u(e,`src`,`services`))}/`;return{name:`canvas-kit-banned-imports`,transform(e,r){let i=n(r.split(`?`)[0]),a=h.find(e=>i.includes(`/node_modules/${e}/`));if(a)throw Error(`The kit imports ${a} (${i}). A kit draws from its props only; the container that renders it holds the state and the calls.`);if(i.startsWith(t))throw Error(`The kit imports ${i}, which is in src/services. A kit draws from its props only; move the call into the container.`);return null}}}async function E({root:e,kit:t,platform:n,entryFile:i,libraryFile:a,libraryNames:o,productNames:s}){let c=r[n],l=await p({configFile:!1,root:e,logLevel:`warn`,publicDir:!1,envDir:!1,plugins:[w(C({kit:t,platform:n,entryFile:i,libraryFile:a,libraryNames:o,productNames:s})),T(e)],esbuild:{jsx:`automatic`,jsxImportSource:`react`,include:/\.[cm]?[jt]sx?$/},build:{write:!1,minify:!0,target:`es2022`,cssCodeSplit:!1,lib:{entry:v,formats:[`es`],fileName:()=>`kit.js`},rollupOptions:{input:v,external:e=>c.some(t=>e===t||e.startsWith(`${t}/`))}}}),u=(Array.isArray(l)?l:[l]).flatMap(e=>e.output),d=u.find(e=>e.type===`chunk`&&e.isEntry);if(!d)throw Error(`The bundle of ${t} has no entry module.`);let f=u.filter(e=>e.type===`asset`&&e.fileName.endsWith(`.css`)).map(e=>typeof e.source==`string`?e.source:Buffer.from(e.source).toString(`utf8`)).join(`
|
|
3
|
+
`);return{script:d.code,styles:f}}async function D({configFile:e,outDir:n}){let r=d(e),f=d(n);if(c(f))throw Error(`${f} already exists. A release folder is never overwritten; choose a new folder.`);let p=x(r),m=l(r),h=d(m,p.entry);if(!c(h))throw Error(`The kit entry ${h} does not exist.`);S(m);let g=p.rolesFile===void 0?void 0:d(m,p.rolesFile),{manifest:_,warnings:v}=a({projectRoot:m,kit:p.kit,platform:p.platform,entry:h,libraryPackage:p.libraryPackage,rolesFile:g,rendererProtocolVersion:p.rendererProtocolVersion,phoneStyleSupportFile:d(m,p.phoneStyleSupportFile)}),y=_.components.filter(({source:e})=>e===p.libraryPackage).map(({name:e})=>e),b=_.components.filter(({source:e})=>e!==p.libraryPackage).map(({name:e})=>e),{script:C,styles:w}=await E({root:m,kit:p.kit,platform:p.platform,entryFile:h,libraryFile:i(m,p.libraryPackage).entryFile,libraryNames:y,productNames:b}),T=t(u(m,`package.json`));if(!T.version)throw Error(`${u(m,`package.json`)} needs a version; the release is stamped with it.`);let D={"manifest.json":`${JSON.stringify(_,null,2)}\n`,"kit.js":C,"kit.css":w},O={name:p.kit,version:T.version,platform:p.platform,kitModuleVersion:1,rendererProtocolVersion:p.rendererProtocolVersion,library:_.library,files:Object.fromEntries(Object.entries(D).map(([e,t])=>[e,o(t)]))};return s(f,D,O),{outDir:f,release:O,manifest:_,warnings:v}}export{D as buildKitRelease,x as readConfig};
|
package/dist/cli.js
ADDED
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
import{buildKitRelease as e}from"./build.js";import{resolve as t}from"node:path";var n=`Usage: canvas-kit build --config <file> --out <dir>
|
|
3
|
+
|
|
4
|
+
Builds a product kit release into <dir>: kit.js, kit.css, manifest.json and release.json.
|
|
5
|
+
<dir> must not exist; a release folder is never overwritten.`;function r(e){if(e.length===0||e.includes(`--help`)||e.includes(`-h`))return{help:!0};let[t,...n]=e,r={};for(let e=0;e<n.length;e+=1){let t=n[e];if(t!==`--config`&&t!==`--out`)throw Error(`Unknown argument ${t}.`);let i=n[e+1];if(i===void 0||i.startsWith(`--`))throw Error(`${t} needs a value.`);r[t.slice(2)]=i,e+=1}return{command:t,options:r}}async function i(i){let a=r(i);if(a.help){process.stdout.write(`${n}\n`);return}if(a.command!==`build`)throw Error(`Unknown command ${a.command}. The only command is build.`);if(!a.options.config||!a.options.out)throw Error(`build needs --config and --out.`);let o=await e({configFile:t(a.options.config),outDir:t(a.options.out)});for(let e of o.warnings)process.stderr.write(`warning: ${e}\n`);process.stdout.write(`Built ${o.release.name} (${o.release.platform}): ${o.manifest.components.length} components. Release written to ${o.outDir}.\n`)}i(process.argv.slice(2)).catch(e=>{process.stderr.write(`canvas-kit: ${e.message}\n`),process.exitCode=1});export{};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
import{readText as e}from"./files.js";import{existsSync as t}from"node:fs";import{dirname as n,join as r,resolve as i}from"node:path";import a from"@babel/parser";var o=`function`,s=8,c=2,l=120,u=[`ForwardRefExoticComponent`,`FC`,`FunctionComponent`,`ComponentType`,`MemoExoticComponent`],d=[`Array`,`ReadonlyArray`,`Set`,`ReadonlySet`],f=/(^i|I)con$/,p=/(Href|href|Url|url)$/,m=new Map,h=new Set;function g(e,t){return e<t?-1:+(e>t)}function _(e){return[...new Set(e)].sort(g)}function v(e){return e.type===`Identifier`?e.name:e.type===`StringLiteral`?e.value:null}function y(e){let t=e.type===`TSImportType`?e.qualifier:e.typeName;return t?t.type===`TSQualifiedName`?t.right.name:t.name:null}function b(e){switch(e.type){case`TSDeclareFunction`:case`FunctionDeclaration`:case`TSInterfaceDeclaration`:case`TSTypeAliasDeclaration`:return[[e.id.name,e]];case`VariableDeclaration`:return e.declarations.filter(e=>e.id.type===`Identifier`).map(e=>[e.id.name,e]);default:return[]}}function x(t){if(m.has(t))return m.get(t);let n=e(t),r=a.parse(n,{sourceType:`module`,plugins:[`typescript`]}),i={declarations:new Map,imports:new Map,exports:[],defaultDeclaration:null,source:n};for(let e of r.program.body)if(e.type===`ImportDeclaration`)for(let t of e.specifiers)t.type===`ImportSpecifier`&&i.imports.set(t.local.name,{source:e.source.value,imported:v(t.imported)});else if(e.type===`ExportAllDeclaration`)i.exports.push({star:!0,source:e.source.value});else if(e.type===`ExportDefaultDeclaration`)i.defaultDeclaration=e.declaration,i.exports.push({name:`default`,local:`default`});else if(e.type===`ExportNamedDeclaration`&&e.source)for(let t of e.specifiers)i.exports.push({name:t.exported.name,local:t.local.name,source:e.source.value});else{let t=e.type===`ExportNamedDeclaration`,n=t?e.declaration:e;for(let[e,r]of n?b(n):[])i.declarations.set(e,r),t&&i.exports.push({name:e,local:e});if(t)for(let t of e.specifiers)i.exports.push({name:t.exported.name,local:t.local.name})}return m.set(t,i),i}function S(e,a){if(!a.startsWith(`.`))return null;let o=i(n(e),a).replace(/\.(jsx?|tsx?)$/,``);for(let e of[`${o}.d.ts`,r(o,`index.d.ts`)])if(t(e))return e;throw Error(`Cannot resolve ${a} from ${e}`)}function C(e,t=new Set){let n=new Map;if(t.has(e))return n;t.add(e);for(let r of x(e).exports){if(r.star){let i=S(e,r.source);for(let[e,r]of i?C(i,t):[])e!=="default"&&!n.has(e)&&n.set(e,r);continue}let i=r.source===void 0?e:S(e,r.source);i&&n.set(r.name,{file:i,local:r.local})}return n}function w(e,t=new Set){let n=`${e.file}#${e.local}`;if(t.has(n))return null;t.add(n);let r=x(e.file);if(r.declarations.has(e.local))return e;let i=r.exports.find(t=>t.name===e.local&&t.source!==void 0),a=i&&S(e.file,i.source);return a?w({file:a,local:i.local},t):null}function T(e){return e.local==="default"?e:w(e)}function E(e){let t=T(e);if(!t)return null;let{declarations:n,defaultDeclaration:r}=x(t.file),i=t.local==="default"?r?.type===`Identifier`?n.get(r.name):r:n.get(t.local);return i?.type===`TSDeclareFunction`||i?.type===`FunctionDeclaration`?i:null}function D(e,t,n){let r=e.params[0];if(!r)return[];let i=(r.type===`AssignmentPattern`?r.left:r).typeAnnotation?.typeAnnotation;if(!i)return null;if(i.type===`TSTypeLiteral`)return i.members;let a=y(i);if(i.type!==`TSTypeReference`||!a?.endsWith(`Props`))return null;let o=x(t.file).declarations.get(a);if(o?.type===`TSInterfaceDeclaration`)return o.body.body;if(o?.type===`TSTypeAliasDeclaration`&&o.typeAnnotation.type===`TSTypeLiteral`)return o.typeAnnotation.members;throw Error(`${n}: ${a} is not an object type in ${t.file}`)}function O(e,t){let n=x(e),r=n.declarations.get(t);if(r)return{file:e,declared:r};let i=n.imports.get(t),a=i&&S(e,i.source);if(!a)return null;let o=w({file:a,local:i.imported});return o?{file:o.file,declared:x(o.file).declarations.get(o.local)}:null}function k(e,t,n){if(e===`ReactNode`||e===`ReactElement`)return{type:`node`};if(d.includes(e))return{type:`array`};if(e===`Record`)return{type:`object`};if(e===`Date`)return{type:`string`};if(e===`Function`)return o;if(e===`SlotIcon`)return{type:`node`};if(!t||n>=s)return null;let r=O(t,e);return r?.declared?.type===`TSTypeAliasDeclaration`?R(r.declared.typeAnnotation,r.file,n+1):r?.declared?.type===`TSInterfaceDeclaration`?V(r.declared.body.body,r.file):null}function A(e){return e.type===`TSBooleanKeyword`||e.type===`TSLiteralType`&&e.literal.type===`BooleanLiteral`}function j(e){return e.type===`TSLiteralType`&&e.literal.type===`StringLiteral`}function M(e){return e.type===`TSObjectKeyword`||e.type===`TSTypeLiteral`}function N(e){return e?.type===`TSQualifiedName`&&e.left.type===`Identifier`&&e.left.name===`JSX`&&e.right.name===`Element`}function P(e){return e.type===`TSTypeReference`&&[`File`,`Blob`].includes(y(e))}function F(e,t,n){let r=e.filter(e=>e.type!==`TSNullKeyword`&&e.type!==`TSUndefinedKeyword`&&!P(e)),i=e=>r.every(t=>t.type===`TSLiteralType`&&t.literal.type===e);if(r.length===0)return null;if(i(`StringLiteral`))return{type:`enum`,enum:_(r.map(e=>e.literal.value))};if(i(`BooleanLiteral`)||r.some(A)&&r.every(e=>A(e)||j(e)||M(e)))return{type:`boolean`};if(i(`NumericLiteral`))return{type:`number`};if(r.length===1&&r[0].type!==`TSLiteralType`)return R(r[0],t,n);let a=r.flatMap(e=>I(e,t,n));if(a.length>0&&!a.includes(null))return{type:`enum`,enum:_(a)};let s=new Set(r.map(e=>L(e,t,n)));return s.has(`node`)?{type:`node`}:s.size===2&&s.has(`string`)&&s.has(`number`)?{type:`stringOrNumber`}:s.size===1&&!s.has(null)?{type:[...s][0]}:r.every(e=>e.type!==`TSLiteralType`)&&r.map(e=>R(e,t,n)).every(e=>e&&e!==o&&[`object`,`array`].includes(e.type))?{type:`any`}:null}function I(e,t,n){if(e.type===`TSLiteralType`)return e.literal.type===`StringLiteral`?[e.literal.value]:[null];let r=R(e,t,n);return r?.type===`enum`?r.enum:[null]}function L(e,t,n){if(e.type===`TSLiteralType`){let t=e.literal.type;return t===`StringLiteral`?`string`:t===`NumericLiteral`?`number`:t===`BooleanLiteral`?`boolean`:null}let r=R(e,t,n);return r?.type===`enum`?`string`:r&&r!==o&&[`node`,`string`,`number`,`boolean`].includes(r.type)?r.type:null}function R(e,t,n=0){switch(e.type){case`TSParenthesizedType`:return R(e.typeAnnotation,t,n);case`TSAnyKeyword`:case`TSUnknownKeyword`:return{type:`any`,anyUnknown:!0};case`TSStringKeyword`:return{type:`string`};case`TSNumberKeyword`:return{type:`number`};case`TSBooleanKeyword`:return{type:`boolean`};case`TSArrayType`:return H(e.elementType,t,n);case`TSTypeLiteral`:return V(e.members,t);case`TSFunctionType`:return o;case`TSLiteralType`:return F([e],t,n);case`TSUnionType`:return F(e.types,t,n);case`TSTypeReference`:return N(e.typeName)?{type:`node`}:d.includes(y(e))&&e.typeParameters?.params.length===1?H(e.typeParameters.params[0],t,n):k(y(e),t,n);case`TSImportType`:return N(e.qualifier)?{type:`node`}:k(y(e),null,n);default:return null}}function z(e,t){return p.test(e)&&(t===`string`||t===`any`)?`url`:t}function B(e,t){if(h.size>=c||h.has(e))return null;h.add(e);try{return U(e,t)}finally{h.delete(e)}}function V(e,t){let n=B(e,t);return n?{type:`object`,fields:n.props,skippedFields:n.skippedProps}:{type:`object`}}function H(e,t,n){let r=R(e,t,n);return r?.fields?{type:`array`,itemFields:r.fields,skippedFields:r.skippedFields}:{type:`array`}}function U(e,t){let n=[],r=[],i=!1;for(let a of e){if(a.type!==`TSPropertySignature`)continue;let e=v(a.key);if(!e)continue;if(e===`children`){i=!0;continue}let s=a.typeAnnotation?.typeAnnotation??{type:`TSAnyKeyword`},c=R(s,t);if(c===o)continue;if(!c){r.push({name:e,type:W(s,t)});continue}let{type:l,enum:u,anyUnknown:d,fields:p,itemFields:m,skippedFields:h=[]}=c;for(let t of h)r.push({...t,name:`${e}${l===`array`?`[]`:``}.${t.name}`});n.push({name:e,type:z(e,l===`node`&&f.test(e)?`icon`:l),...u?{enum:u}:{},...p?{fields:p}:{},...m?{itemFields:m}:{},required:!a.optional&&!d})}return n.sort((e,t)=>g(e.name,t.name)),{props:n,acceptsChildren:i,skippedProps:r}}function W(e,t){let n=t?x(t).source:null;if(!n)return e.type;let r=n.slice(e.start,e.end).replace(/\s+/g,` `);return r.length>l?`${r.slice(0,l)}...`:r}function G(e,t){return!e||typeof e!=`object`?!1:e.type===`TSTypeReference`&&y(e)===t||Object.entries(e).some(([e,n])=>e!==`loc`&&(Array.isArray(n)?n.some(e=>G(e,t)):G(n,t)))}function K(e){if(!e||![`TSTypeReference`,`TSImportType`].includes(e.type)||y(e)!==`ForwardRefExoticComponent`)return null;let[t]=(e.typeParameters??e.typeArguments)?.params??[],n=(t?.type===`TSIntersectionType`?t.types:[t]).filter(e=>e?.type===`TSTypeLiteral`);return n.length?n.flatMap(e=>e.members):null}function q(e){let t=T(e);if(!t)return null;let{declarations:n,defaultDeclaration:r}=x(t.file),i=t.local==="default"?r?.type===`Identifier`&&n.get(r.name):n.get(t.local);return i?.type===`VariableDeclarator`?{node:i,declarations:n}:null}function J(e){let t=q(e)?.node.id.typeAnnotation?.typeAnnotation;return[`TSTypeReference`,`TSImportType`].includes(t?.type)&&u.includes(y(t))}function Y(e,t){let n=q(e);if(!n)return null;let{node:r,declarations:i}=n,a=`${t}Props`;if(!G(r.id.typeAnnotation,a))return K(r.id.typeAnnotation?.typeAnnotation);let o=i.get(a);return o?.type===`TSInterfaceDeclaration`?o.body.body:o?.type===`TSTypeAliasDeclaration`&&o.typeAnnotation.type===`TSTypeLiteral`?o.typeAnnotation.members:null}function X(e,{namedConsts:t=!1,kit:n=``}={}){m=new Map,h.clear();let r=[],i=[];for(let[a,o]of C(e)){if(!/^[A-Z][A-Za-z0-9]*$/.test(a))continue;let s=E(o),c=T(o),l=s?D(s,c,a):t?Y(o,a):null;if(!l){(s||t&&J(o))&&i.push(`Component left out, its props could not be read: ${n} ${a}`);continue}let u=U(l,c?.file);if(u.skippedProps.length>0){let e=u.skippedProps.map(({name:e,type:t})=>`${e} (${t})`).join(`, `);i.push(`Skipped props, no manifest type: ${n} ${a}: ${e}`)}r.push({name:a,acceptsChildren:u.acceptsChildren,props:u.props,file:c?.file??e})}return r.sort((e,t)=>g(e.name,t.name)),{components:r,warnings:i}}export{X as collectComponents};
|
package/dist/files.js
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
import{existsSync as e,readFileSync as t}from"node:fs";import{dirname as n,join as r}from"node:path";function i(n){if(!e(n))throw Error(`Missing ${n}. Run pnpm install in the product first.`);return t(n,`utf8`)}function a(e){return JSON.parse(i(e))}function o(e){return e.replace(/\\/g,`/`)}function s(t,i){let a=t;for(;;){let t=r(a,`node_modules`,...i.split(`/`));if(e(r(t,`package.json`)))return t;let o=n(a);if(o===a)return null;a=o}}export{s as findPackageDir,a as readJson,i as readText,o as toPosix};
|
package/dist/index.js
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
import{KIT_MODULE_EXTERNALS as e,defineKit as t,kitModuleVersion as n}from"./kitModule.js";import{readManifest as r}from"./manifest.js";import{readReleaseManifest as i}from"./release.js";import{buildKitRelease as a,readConfig as o}from"./build.js";export{e as KIT_MODULE_EXTERNALS,a as buildKitRelease,t as defineKit,n as kitModuleVersion,o as readConfig,r as readManifest,i as readReleaseManifest};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
var e=1,t=Object.freeze({Web:[`react`,`react-dom`,`react/jsx-runtime`],Phone:[`react`,`react-dom`,`react/jsx-runtime`,`react-native`,`react-native-svg`]});function n({kit:e,platform:n,componentMap:r}){if(typeof e!=`string`||e===``)throw Error(`defineKit needs the kit key, a non-empty string.`);if(!Object.hasOwn(t,n))throw Error(`defineKit: platform ${JSON.stringify(n)} is not Web or Phone.`);if(typeof r!=`object`||!r)throw Error(`defineKit: componentMap of ${e} must be an object of components.`);let i={};for(let[t,n]of Object.entries(r)){if(n===null||typeof n!=`function`&&typeof n!=`object`)throw Error(`defineKit: ${e} component ${t} is not a React component.`);i[t]=n}return{kitModuleVersion:1,kit:e,platform:n,componentMap:Object.freeze(i)}}export{t as KIT_MODULE_EXTERNALS,n as defineKit,e as kitModuleVersion};
|
package/dist/manifest.js
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
import{findPackageDir as e,readJson as t,readText as n,toPosix as r}from"./files.js";import"./kitModule.js";import{collectComponents as i}from"./declarations.js";import{PHONE_EXCLUDED_COMPONENTS as a,applyPhoneActions as o,phoneIcons as s,phoneTokens as c}from"./phone.js";import l from"./styleKeyTable.js";import{colourMeanings as u,webIcons as d,webTokens as f}from"./tokens.js";import{createRequire as p}from"node:module";import{existsSync as m,mkdtempSync as h,rmSync as g}from"node:fs";import{dirname as _,join as v,relative as y,resolve as b}from"node:path";import{execFileSync as x}from"node:child_process";import{tmpdir as S}from"node:os";var C=/^[a-z][a-z0-9-]{1,39}$/,w=[`Web`,`Phone`],T=[`title`,`navigation`],E=v(_(p(import.meta.url).resolve(`typescript/package.json`)),`bin`,`tsc`),D=[`.jsx`,`.js`,`.tsx`,`.ts`,`.mjs`];function O(n,r){let i=e(n,r);if(!i)throw Error(`${r} is not installed for ${n}. Run pnpm install there.`);let a=t(v(i,`package.json`)),o=a.exports?.[`.`],s=a.types??(o&&typeof o==`object`?o.types:void 0),c=(typeof o==`string`?o:o&&typeof o==`object`?o.import??o.default:void 0)??a.main;if(!s)throw Error(`${r} declares no types, and the manifest reads its declaration files.`);if(!c)throw Error(`${r} declares no entry file for its runtime.`);return{dir:i,pkg:a,typesFile:v(i,s),entryFile:v(i,c)}}function k(t){let n=e(t,`@webority/theme`);if(!n)throw Error(`@webority/theme is not installed for ${t}. Run pnpm install.`);return n}function A(e,n,r){let i=t(v(e,`package.json`)),a=i.dependencies?.[n]??i.devDependencies?.[n];if(/^\d+\.\d+\.\d+$/.test(a??``)&&a!==r)throw Error(`${n} is pinned to ${a} in package.json but ${r} is installed. Run pnpm install first.`)}function j(e,t){let n=h(v(S(),`canvas-kit-declarations-`));try{x(process.execPath,[E,`--allowJs`,`--declaration`,`--emitDeclarationOnly`,`--jsx`,`react-jsx`,`--module`,`esnext`,`--moduleResolution`,`bundler`,`--target`,`es2022`,`--skipLibCheck`,`--rootDir`,e,`--outDir`,n,t],{cwd:e,encoding:`utf8`,stdio:`pipe`})}catch(e){throw g(n,{recursive:!0,force:!0}),Error(`Could not read the declarations of ${t}: ${e.stdout||e.stderr||e.message}`)}return n}function M(e,t,n){let i=y(t,n).replace(/\.d\.ts$/,``);for(let t of D)if(m(v(e,`${i}${t}`)))return r(`${i}${t}`);throw Error(`No source file for the declarations in ${n}`)}function N(e){return e.filter(e=>e.type===`array`&&(e.itemFields??[]).some(e=>[`href`,`to`].includes(e.name))).map(e=>e.name)}function P(e,n){if(!n)return;let r=t(n);if(typeof r!=`object`||!r||Array.isArray(r))throw Error(`${n} must be an object from component name to role.`);for(let[t,i]of Object.entries(r)){let r=e.find(e=>e.name===t);if(!r)throw Error(`${n} names ${t}, which the kit does not have.`);if(!T.includes(i))throw Error(`${n}: ${t} has role ${JSON.stringify(i)}; a role is title or navigation.`);r.role=i}}function F(e){let n=t(e);if(n?.schema!==1)throw Error(`${e} has schema ${n?.schema}; this reader reads schema 1.`);let r=l.map(({name:e})=>e),i=n.styleKeys??{},a=r.filter(e=>typeof i[e]!=`boolean`),o=Object.keys(i).filter(e=>!r.includes(e));if(a.length>0||o.length>0)throw Error(`${e} must list exactly the style keys of the style key table, each true or false. Missing or not a boolean: ${a.join(`, `)||`none`}. Not in the table: ${o.join(`, `)||`none`}.`);if(!n.itemActions)throw Error(`${e} has no itemActions; the phone kit's action lists come from it.`);return{flags:i,itemActions:n.itemActions}}function I({projectRoot:e,kit:r,platform:p,entry:m,libraryPackage:h,rolesFile:_,rendererProtocolVersion:x,phoneStyleSupportFile:S}){if(!C.test(r??``))throw Error(`kit ${JSON.stringify(r)} must be 2 to 40 characters: lowercase letters, digits and hyphens, starting with a letter.`);if(!w.includes(p))throw Error(`platform must be Web or Phone, not ${JSON.stringify(p)}.`);if(!Number.isInteger(x)||x<1)throw Error(`rendererProtocolVersion must be a positive integer, not ${JSON.stringify(x)}.`);let T=b(e),E=O(T,h);A(T,h,E.pkg.version);let D=F(S),I=i(E.typesFile,{namedConsts:!0,kit:h}),L=p===`Phone`?I.components.filter(({name:e})=>!a.has(e)):I.components,R=b(m);if(y(T,R).startsWith(`..`))throw Error(`The kit entry ${R} is outside the product folder ${T}.`);let z=j(T,R),B,V;try{B=i(v(z,y(T,R)).replace(/\.[^./\\]+$/,`.d.ts`),{kit:r}),V=new Map(B.components.map(e=>[e.name,M(T,z,e.file)]))}finally{g(z,{recursive:!0,force:!0})}let H=new Set(L.map(({name:e})=>e)),U=B.components.filter(({name:e})=>H.has(e)).map(({name:e})=>e);if(U.length>0)throw Error(`The kit names ${U.join(`, `)} as ${h} already has them; rename the product components.`);let W=[...L.map(e=>({...e,source:h})),...B.components.map(e=>({...e,source:V.get(e.name)}))].sort((e,t)=>e.name<t.name?-1:+(e.name>t.name)).map(({name:e,acceptsChildren:t,props:n,source:r})=>({name:e,acceptsChildren:t,props:n,itemsTakeAction:p===`Web`?N(n):[],takesAction:[],source:r}));p===`Phone`&&o(W,D.itemActions),P(W,_);let G,K;if(p===`Web`){let e=k(T);G=f(n(v(e,`scss`,`_tokens.scss`))),G.colorMeanings=u(G.color,t(v(e,`token-meanings.json`))),K=d(v(E.dir,`dist`))}else G=c(v(E.dir,`lib`,`module`,`theme`,`tokens.js`)),K=s(v(E.dir,`lib`,`typescript`,`module`,`components`,`AppIcon`,`catalog.g.d.ts`));return{manifest:{kit:`Product`,library:{name:E.pkg.name,version:E.pkg.version},rendererProtocolVersion:x,platform:p,kitModuleVersion:1,productKit:null,components:W,tokens:G,icons:K,styleKeys:l.map(({name:e,type:t,values:n,appliesTo:r,description:i})=>({name:e,type:t,values:n,appliesTo:r,phoneSupported:D.flags[e],description:i}))},warnings:[...I.warnings,...B.warnings]}}export{O as libraryFiles,I as readManifest,F as readPhoneSupport};
|
package/dist/phone.js
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
import{readText as e}from"./files.js";import t from"@babel/parser";var n=new Set([`Form`,`NetworkStatusBanner`,`SkeletonClockProvider`,`SkeletonProvider`,`SkeletonSkip`,`ThemeProvider`,`ToastProvider`,`Box`,`Text`]),r=[`sans`];function i(n){return t.parse(e(n),{sourceType:`module`,plugins:[`typescript`]})}function a(e){return[...new Set(e)].sort((e,t)=>e<t?-1:+(e>t))}function o(e){return e.type===`Identifier`?e.name:e.type===`StringLiteral`?e.value:null}function s(e){let t=new Map;for(let n of e.program.body){let e=n.type===`ExportNamedDeclaration`?n.declaration:n;if(e?.type===`VariableDeclaration`)for(let n of e.declarations)n.id.type===`Identifier`&&t.set(n.id.name,n.init)}return t}function c(e,t,n){let r=t;for(let t=0;r?.type===`Identifier`;t+=1){if(t>10||!e.has(r.name))throw Error(`${r.name} in ${n} is not a constant the reader can follow.`);r=e.get(r.name)}return r}function l(e,t,n,r){let i=n.properties.find(e=>e.type===`ObjectProperty`&&o(e.key)===r);if(!i)throw Error(`${r} is missing from the theme in ${t}`);return c(e,i.value,t)}function u(e){return e.properties.filter(e=>e.type===`ObjectProperty`).map(e=>o(e.key))}function d(e,t,n,r=``){return n.properties.flatMap(n=>{if(n.type!==`ObjectProperty`)return[];let i=`${r}${o(n.key)}`,a=c(e,n.value,t);return a.type===`StringLiteral`?[i]:a.type===`ObjectExpression`?d(e,t,a,`${i}.`):[]})}function f(e){let t=s(i(e));if(!t.has(`lightTheme`))throw Error(`lightTheme is not declared in ${e}`);let n=c(t,t.get(`lightTheme`),e),o=l(t,e,n,`typography`);return{color:a(d(t,e,l(t,e,n,`colors`))),space:a(u(l(t,e,n,`spacing`))),radius:a(u(l(t,e,n,`radius`))),shadow:a(u(l(t,e,n,`shadows`))),font:r,text:a(u(l(t,e,o,`fontSize`)))}}function p(e){let t=i(e).program.body.map(e=>e.type===`ExportNamedDeclaration`?e.declaration:e).find(e=>e?.type===`TSTypeAliasDeclaration`&&e.id.name===`IconName`);if(t?.typeAnnotation.type!==`TSUnionType`)throw Error(`IconName union not found in ${e}`);return a(t.typeAnnotation.types.map(t=>{if(t.type!==`TSLiteralType`||t.literal.type!==`StringLiteral`)throw Error(`IconName in ${e} has a member that is not a string literal`);return t.literal.value}))}function m(e,t){for(let[n,r]of[[`itemsTakeAction`,`array`],[`takesAction`,`object`]])for(let[i,o]of Object.entries(t[n]??{})){let t=e.find(({name:e})=>e===i);if(!t)throw Error(`phoneStyleSupport.json ${n} names ${i}, which the kit does not have.`);for(let e of o)if(t.props.find(({name:t})=>t===e)?.type!==r)throw Error(`phoneStyleSupport.json ${n} names ${i}.${e}, which is not a prop of type ${r} in the kit.`);t[n]=a(o)}}export{n as PHONE_EXCLUDED_COMPONENTS,m as applyPhoneActions,p as phoneIcons,f as phoneTokens};
|
package/dist/release.js
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
import{readJson as e}from"./files.js";import{RELEASE_FILE as t,changedMessage as n,checkStampFiles as r}from"./releaseStamp.js";import{existsSync as i,mkdirSync as a,readFileSync as o,renameSync as s,rmSync as c,writeFileSync as l}from"node:fs";import{dirname as u,join as d}from"node:path";import{createHash as f}from"node:crypto";function p(e){let t=Buffer.from(e);return{sha256:f(`sha256`).update(t).digest(`hex`),bytes:t.length}}function m(e,n,r){if(i(e))throw Error(`${e} already exists. A release folder is never overwritten; choose a new folder.`);a(u(e),{recursive:!0});let o=`${e}.staging-${process.pid}-${Date.now()}`;a(o);try{for(let[e,t]of Object.entries(n))l(d(o,e),t,{flag:`wx`});l(d(o,t),`${JSON.stringify(r,null,2)}\n`,{flag:`wx`}),s(o,e)}catch(e){throw c(o,{recursive:!0,force:!0}),e}}function h(a){let s=d(a,t);if(!i(s))throw Error(`${a} has no ${t}; it is not a kit release.`);let c=e(s);r(c,a);for(let[e,t]of Object.entries(c.files)){let r=d(a,e);if(!i(r))throw Error(`${e} is missing from ${a}.`);let s=p(o(r));if(s.sha256!==t.sha256||s.bytes!==t.bytes)throw Error(n(e,a))}return{release:c,manifest:e(d(a,`manifest.json`))}}export{p as digest,h as readReleaseManifest,m as writeReleaseFolder};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
var e=`release.json`,t=[`manifest.json`,`kit.js`,`kit.css`];function n(n,r){for(let i of t)if(!n?.files?.[i])throw Error(`${e} in ${r} does not stamp ${i}.`)}function r(t,n){return`${t} in ${n} does not match ${e}; a published release is never changed, so rebuild it.`}export{t as RELEASE_CONTENT,e as RELEASE_FILE,r as changedMessage,n as checkStampFiles};
|
package/dist/spec.d.ts
ADDED
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
// The answer to a canvas:request of kind spec: the drawn nodes of the screen, or of the subtree under the node asked for.
|
|
2
|
+
|
|
3
|
+
export interface CanvasSpecBox {
|
|
4
|
+
// Pixels, measured from the top left of the drawing.
|
|
5
|
+
x: number;
|
|
6
|
+
y: number;
|
|
7
|
+
width: number;
|
|
8
|
+
height: number;
|
|
9
|
+
}
|
|
10
|
+
|
|
11
|
+
// The value a token resolves to in each colour mode.
|
|
12
|
+
export interface CanvasSpecTokenValues {
|
|
13
|
+
light: string;
|
|
14
|
+
dark: string;
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
export interface CanvasSpecNode {
|
|
18
|
+
// The node id as the document holds it; an instance inside a placed component is "<instanceId>.<innerId>".
|
|
19
|
+
id: string;
|
|
20
|
+
// The component the node draws: a block type (Box, Text, Image, Icon, Vector) or a library component name.
|
|
21
|
+
component: string;
|
|
22
|
+
box: CanvasSpecBox;
|
|
23
|
+
// The CSS the renderer applied to the node's element, keyed by property name.
|
|
24
|
+
styles: Record<string, string>;
|
|
25
|
+
// Each style key that names a token, keyed by style key ("color", or "border.color" for a part of an object).
|
|
26
|
+
tokens: Record<string, CanvasSpecTokenValues>;
|
|
27
|
+
// The text a Text node draws.
|
|
28
|
+
text?: string;
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
export interface CanvasSpec {
|
|
32
|
+
nodes: CanvasSpecNode[];
|
|
33
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
var e=[{name:`layout`,type:`enum`,values:[`row`,`column`,`grid`,`overlay`,`free`],appliesTo:`any`,description:`How children are placed: row, column, grid, overlay (stacked in one cell) or free (x and y).`},{name:`gap`,type:`token`,values:[`space`],appliesTo:`any`,description:`Space between children: a space token or px.`},{name:`rowGap`,type:`token`,values:[`space`],appliesTo:`any`,description:`Space between rows; overrides gap.`},{name:`columnGap`,type:`token`,values:[`space`],appliesTo:`any`,description:`Space between columns; overrides gap.`},{name:`padding`,type:`token`,values:[`space`],appliesTo:`any`,description:`Inside space: a space token, px, or four px values [top, right, bottom, left]. Counted inside width and height.`},{name:`margin`,type:`token`,values:[`space`],appliesTo:`any`,description:`Outside space: px (negative allowed), a space token, auto, or four values, each px or auto.`},{name:`align`,type:`enum`,values:[`start`,`center`,`end`,`stretch`,`baseline`],appliesTo:`any`,description:`Cross-axis alignment of the children; baseline lines text up on its baseline.`},{name:`alignSelf`,type:`enum`,values:[`start`,`center`,`end`,`stretch`,`baseline`],appliesTo:`any`,description:`The node's own cross-axis alignment.`},{name:`justify`,type:`enum`,values:[`start`,`center`,`end`,`between`,`around`],appliesTo:`any`,description:`Main-axis distribution of the children.`},{name:`wrap`,type:`boolean`,values:[],appliesTo:`any`,description:`Children wrap onto new lines.`},{name:`columns`,type:`list`,values:[],appliesTo:`any`,description:`Grid columns: a count of equal columns, or a list of px numbers and fr shares such as [120, 1fr, 30] (fr shares are strings).`},{name:`width`,type:`size`,values:[`fill`,`hug`],appliesTo:`any`,description:`px, fill (the space the parent gives), hug (the content) or a percent string such as 76%.`},{name:`height`,type:`size`,values:[`fill`,`hug`],appliesTo:`any`,description:`px, fill, hug or a percent string.`},{name:`minWidth`,type:`size`,values:[],appliesTo:`any`,description:`px or a percent string.`},{name:`maxWidth`,type:`size`,values:[],appliesTo:`any`,description:`px or a percent string.`},{name:`minHeight`,type:`size`,values:[],appliesTo:`any`,description:`px or a percent string.`},{name:`maxHeight`,type:`size`,values:[],appliesTo:`any`,description:`px or a percent string.`},{name:`grow`,type:`number`,values:[],appliesTo:`any`,description:`Share of the free space this node takes in a row or column.`},{name:`shrink`,type:`number`,values:[],appliesTo:`any`,description:`How much the node shrinks when space runs out; 0 keeps its size.`},{name:`position`,type:`enum`,values:[`absolute`],appliesTo:`any`,description:`absolute places the node at x and y over its parent box, out of the flow.`},{name:`x`,type:`number`,values:[],appliesTo:`any`,description:`Left offset in px when the parent layout is free or position is absolute.`},{name:`y`,type:`number`,values:[],appliesTo:`any`,description:`Top offset in px, by the same rule as x.`},{name:`zIndex`,type:`integer`,values:[],appliesTo:`any`,description:`Stacking order among siblings, -100 to 100.`},{name:`background`,type:`token`,values:[`color`],appliesTo:`any`,description:`A colour token, a gradient (gradient linear, radial or conic; angle; stops of color and at, a percent from 0 to 100), or a list of 2 to 4 layers, top first.`},{name:`border`,type:`object`,values:[],appliesTo:`any`,description:`width, color and style; width is px or four px values [top, right, bottom, left]; style is solid or dashed.`},{name:`radius`,type:`token`,values:[`radius`],appliesTo:`any`,description:`A radius token or px, or four values [top-left, top-right, bottom-right, bottom-left].`},{name:`shadow`,type:`token`,values:[`shadow`],appliesTo:`any`,description:`A shadow token; it is a CSS box-shadow, so spread works.`},{name:`opacity`,type:`number`,values:[],appliesTo:`any`,description:`0 to 1.`},{name:`blur`,type:`number`,values:[],appliesTo:`any`,description:`Blurs the node itself, in px.`},{name:`backdropBlur`,type:`number`,values:[],appliesTo:`any`,description:`Blurs what is behind the node (frosted glass), in px; give the node a translucent background.`},{name:`overflow`,type:`enum`,values:[`visible`,`hidden`,`scroll`],appliesTo:`any`,description:`What happens to content past the box.`},{name:`font`,type:`token`,values:[`font`],appliesTo:`any`,description:`A font token.`},{name:`text`,type:`token`,values:[`text`],appliesTo:`any`,description:`A type-scale token: size, line height, weight and letter spacing.`},{name:`color`,type:`token`,values:[`color`],appliesTo:`any`,description:`The text colour token.`},{name:`weight`,type:`number`,values:[],appliesTo:`any`,description:`Font weight; overrides the text token.`},{name:`textAlign`,type:`enum`,values:[`left`,`center`,`right`],appliesTo:`any`,description:`Text alignment.`},{name:`lineHeight`,type:`number`,values:[],appliesTo:`any`,description:`Line height; overrides the text token.`},{name:`letterSpacing`,type:`number`,values:[],appliesTo:`any`,description:`Letter spacing in px; overrides the text token.`},{name:`transform`,type:`enum`,values:[`none`,`uppercase`,`lowercase`],appliesTo:`any`,description:`Text case.`},{name:`nowrap`,type:`boolean`,values:[],appliesTo:`Text`,description:`Keeps the text on one line.`},{name:`ellipsis`,type:`boolean`,values:[],appliesTo:`Text`,description:`One line, cut with an ellipsis where it no longer fits.`},{name:`maxLines`,type:`integer`,values:[],appliesTo:`Text`,description:`Stops after this many lines, cut with an ellipsis.`}];export{e as default};
|
package/dist/tokens.js
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
import{readText as e}from"./files.js";import{join as t}from"node:path";var n=[`none`,`xxs`,`xs`,`sm`,`md`,`lg`,`xl`,`2xl`,`3xl`,`4xl`],r=[`sans`,`display`];function i(e){return[...new Set(e)].sort((e,t)=>e<t?-1:+(e>t))}function a(e){let t=e.replace(/\/\*[\s\S]*?\*\//g,``).replace(/(^|\s)\/\/.*$/gm,`$1`),a=new Map;for(let e of t.matchAll(/(?<![\w-])(--wui-[a-z0-9-]+)\s*:([^;]*);/g))a.has(e[1])||a.set(e[1],e[2].replace(/\s+/g,` `).trim());let o=(e,t=0)=>{let n=a.get(e);if(n===void 0)return!1;if(/^(#|rgba?\(|hsla?\()/.test(n))return!0;let r=/^var\((--wui-[a-z0-9-]+)\)$/.exec(n);return r!==null&&t<10&&o(r[1],t+1)},s=e=>i([...a.keys()].filter(t=>t.startsWith(e)).map(t=>t.slice(e.length)));return{color:i([...a.keys()].filter(e=>o(e)&&!e.startsWith(`--wui-font-`)&&!e.startsWith(`--wui-dark-`)).map(e=>e.slice(6))),space:i(n),radius:s(`--wui-radius-`),shadow:s(`--wui-shadow-`),font:i(r),text:s(`--wui-fs-`)}}function o(e,t){return Object.fromEntries(e.map(e=>{let n=t[`--wui-${e}`];if(typeof n!=`string`||n===``)throw Error(`@webority/theme token-meanings.json has no meaning for --wui-${e}; move the theme pin to a version that publishes one.`);return[e,n]}))}function s(n){let r=t(n,`components`,`iconCatalogNames.g.js`),a=e(r),o=/`([^`]+)`\.split\(`\.`\)/.exec(a);if(!o)throw Error(`No icon name list in ${r}`);return i(o[1].split(`.`).filter(Boolean))}export{o as colourMeanings,s as webIcons,a as webTokens};
|
package/package.json
CHANGED
|
@@ -1,6 +1,32 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@webority/canvas-kit",
|
|
3
|
-
"version": "0.
|
|
4
|
-
"
|
|
5
|
-
"
|
|
3
|
+
"version": "0.83.6",
|
|
4
|
+
"description": "Builds product kits for Webority Canvas: a kit bundle, its manifest, and the spec shape the renderers answer.",
|
|
5
|
+
"private": false,
|
|
6
|
+
"type": "module",
|
|
7
|
+
"files": [
|
|
8
|
+
"dist"
|
|
9
|
+
],
|
|
10
|
+
"types": "./dist/spec.d.ts",
|
|
11
|
+
"exports": {
|
|
12
|
+
".": "./dist/index.js",
|
|
13
|
+
"./kitModule": "./dist/kitModule.js",
|
|
14
|
+
"./browser": "./dist/browser.js"
|
|
15
|
+
},
|
|
16
|
+
"bin": {
|
|
17
|
+
"canvas-kit": "./dist/cli.js"
|
|
18
|
+
},
|
|
19
|
+
"dependencies": {
|
|
20
|
+
"@babel/parser": "7.29.8",
|
|
21
|
+
"typescript": "^7.0.2",
|
|
22
|
+
"vite": "^8.0.12"
|
|
23
|
+
},
|
|
24
|
+
"devDependencies": {
|
|
25
|
+
"react": "^19.2.6",
|
|
26
|
+
"@webority/ui-react": "0.83.6"
|
|
27
|
+
},
|
|
28
|
+
"scripts": {
|
|
29
|
+
"build": "vite build --config vite.cli.config.js",
|
|
30
|
+
"test": "node --test"
|
|
31
|
+
}
|
|
6
32
|
}
|