@bridge-ds/core 0.5.1 → 0.7.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/bridge.config.schema.json +69 -0
- package/dist/branch-actions.d.ts +70 -0
- package/dist/combine-branches.d.ts +41 -0
- package/dist/{component-spec-cvrSvIZj.js → component-spec-1z2ih4E3.js} +466 -191
- package/dist/component-spec-1z2ih4E3.js.map +1 -0
- package/dist/component-spec.d.ts +238 -7
- package/dist/config.d.ts +4 -0
- package/dist/docs-proposal.d.ts +82 -0
- package/dist/explorations.d.ts +2 -0
- package/dist/fidelity-references.d.ts +78 -0
- package/dist/fidelity.d.ts +138 -0
- package/dist/github-client.d.ts +89 -0
- package/dist/index.d.ts +11 -0
- package/dist/index.js +1490 -307
- package/dist/index.js.map +1 -1
- package/dist/jira.d.ts +15 -0
- package/dist/library-update.d.ts +145 -0
- package/dist/node/component-specs.d.ts +59 -4
- package/dist/node/index.d.ts +1 -0
- package/dist/node/index.js +2020 -119
- package/dist/node/index.js.map +1 -1
- package/dist/node/spec-css.d.ts +11 -0
- package/dist/node/spec-motion.d.ts +66 -0
- package/dist/products.d.ts +56 -0
- package/dist/review-gate.d.ts +251 -0
- package/dist/rights.d.ts +2 -2
- package/dist/share-branch.d.ts +85 -0
- package/dist/try-in-product.d.ts +16 -0
- package/package.json +1 -1
- package/dist/component-spec-cvrSvIZj.js.map +0 -1
package/dist/jira.d.ts
ADDED
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The Jira key given when a branch is created, normalised ("ds-42 " is "DS-42"), or null when empty. Throws a
|
|
3
|
+
* sentence that says how to fix it when the text is not a key.
|
|
4
|
+
*/
|
|
5
|
+
export declare function parseJiraKey(input: string | null | undefined): string | null;
|
|
6
|
+
/** Whether a text is a Jira key, without throwing (for live field validation). */
|
|
7
|
+
export declare const isJiraKey: (input: string) => boolean;
|
|
8
|
+
/** The Jira key a title starts with ("DS-42 tokens: darker primary" gives "DS-42"), else null. */
|
|
9
|
+
export declare function jiraKeyOf(title: string): string | null;
|
|
10
|
+
/** The title without its leading Jira key. */
|
|
11
|
+
export declare const withoutJiraKey: (title: string) => string;
|
|
12
|
+
/** The pull request title with the key first: "DS-42 tokens: darker primary". Idempotent; no key, no change. */
|
|
13
|
+
export declare function titleWithJiraKey(title: string, key: string | null): string;
|
|
14
|
+
/** The branch name with the key first in its last part: "tokens/DS-42-darker-primary-20261019-1200". */
|
|
15
|
+
export declare function branchWithJiraKey(branch: string, key: string | null): string;
|
|
@@ -0,0 +1,145 @@
|
|
|
1
|
+
import type { GitHubClient, TreeEntry } from './github-client';
|
|
2
|
+
import { type LayoutOptions, type TokenSet } from './token-set';
|
|
3
|
+
import { type ContrastPair } from './wcag';
|
|
4
|
+
import { type MergeChoices, type TokenMergeConflict, type TokenMergeInput, type TokenMergePlan } from './token-merge';
|
|
5
|
+
/** A file of a compare (GET /repos/{o}/{r}/compare/{base}...{head}). */
|
|
6
|
+
export interface CompareFile {
|
|
7
|
+
filename: string;
|
|
8
|
+
status: string;
|
|
9
|
+
previous_filename?: string | undefined;
|
|
10
|
+
sha?: string | null | undefined;
|
|
11
|
+
}
|
|
12
|
+
/** Files both the branch and main changed since they parted, split into token files and the rest (code). */
|
|
13
|
+
export declare function overlap(changeFiles: CompareFile[], libraryFiles: CompareFile[], isTokenFile: (path: string) => boolean): {
|
|
14
|
+
tokenFiles: string[];
|
|
15
|
+
codeFiles: string[];
|
|
16
|
+
};
|
|
17
|
+
/** GitHub lists at most 300 files per compare: past that, Bridge cannot know what both sides touched. */
|
|
18
|
+
export declare const COMPARE_FILE_LIMIT = 300;
|
|
19
|
+
export type ConflictRoute = {
|
|
20
|
+
kind: 'tokens';
|
|
21
|
+
files: string[];
|
|
22
|
+
} | {
|
|
23
|
+
kind: 'code';
|
|
24
|
+
alsoTokens: boolean;
|
|
25
|
+
files: string[];
|
|
26
|
+
};
|
|
27
|
+
/**
|
|
28
|
+
* Who resolves the conflict. Only token files on both sides: the designer, in Bridge. Any code file on both sides, a
|
|
29
|
+
* file list GitHub cut short, or no shared file at all (GitHub saw a conflict Bridge cannot explain): a developer.
|
|
30
|
+
*/
|
|
31
|
+
export declare function conflictRoute(o: {
|
|
32
|
+
tokenFiles: string[];
|
|
33
|
+
codeFiles: string[];
|
|
34
|
+
}, opts?: {
|
|
35
|
+
truncated?: boolean;
|
|
36
|
+
}): ConflictRoute;
|
|
37
|
+
/** A rule from GET /repos/{o}/{r}/rules/branches/{branch}. */
|
|
38
|
+
export interface BranchRuleLike {
|
|
39
|
+
type: string;
|
|
40
|
+
parameters?: {
|
|
41
|
+
dismiss_stale_reviews_on_push?: boolean;
|
|
42
|
+
} | null;
|
|
43
|
+
}
|
|
44
|
+
/**
|
|
45
|
+
* Whether GitHub dismisses approvals when new commits arrive, from the rules that apply to the library branch. True
|
|
46
|
+
* or false when a pull request rule says so; null when no rule says (classic branch protection is not readable
|
|
47
|
+
* without admin rights).
|
|
48
|
+
*/
|
|
49
|
+
export declare function dismissStaleFrom(rules: BranchRuleLike[] | null | undefined): boolean | null;
|
|
50
|
+
/** The commit message of the resolution, so History and the branch say what the person chose. */
|
|
51
|
+
export declare function resolutionMessage(input: {
|
|
52
|
+
library: string;
|
|
53
|
+
conflicts: TokenMergeConflict[];
|
|
54
|
+
choices: MergeChoices;
|
|
55
|
+
who?: string | null | undefined;
|
|
56
|
+
}): string;
|
|
57
|
+
export type LibraryState = 'current' | 'behind' | 'conflict' | 'unknown';
|
|
58
|
+
export interface Freshness {
|
|
59
|
+
state: LibraryState;
|
|
60
|
+
/** Library updates (commits on the library branch) since the change started; null when not read. */
|
|
61
|
+
behindBy: number | null;
|
|
62
|
+
/** The commit the change and the library share. */
|
|
63
|
+
mergeBase: string | null;
|
|
64
|
+
}
|
|
65
|
+
/**
|
|
66
|
+
* How the change stands against the latest library. A conflict (mergeable false) wins: GitHub cannot combine them.
|
|
67
|
+
* Otherwise it is behind when the library has commits the change has not. A shipped or closed change has nothing to
|
|
68
|
+
* bring in. A compare that could not be read says unknown, never "up to date".
|
|
69
|
+
*/
|
|
70
|
+
export declare function freshness<C extends {
|
|
71
|
+
behind_by?: number | undefined;
|
|
72
|
+
merge_base_commit?: {
|
|
73
|
+
sha: string;
|
|
74
|
+
} | null | undefined;
|
|
75
|
+
}>(input: {
|
|
76
|
+
compare: C | null | undefined;
|
|
77
|
+
mergeable: boolean | null | undefined;
|
|
78
|
+
open: boolean;
|
|
79
|
+
}): Freshness;
|
|
80
|
+
/** The compare of main and a branch head, in the shape the conflict reader needs (client.compareDetailed). */
|
|
81
|
+
export interface LibraryCompare {
|
|
82
|
+
mergeBase: string | null;
|
|
83
|
+
baseSha: string | null;
|
|
84
|
+
baseTree: string | null;
|
|
85
|
+
files: CompareFile[];
|
|
86
|
+
}
|
|
87
|
+
export interface LibraryConflicts {
|
|
88
|
+
route: ConflictRoute;
|
|
89
|
+
/** Present for a pure token-file conflict. */
|
|
90
|
+
tokens?: {
|
|
91
|
+
root: string;
|
|
92
|
+
plan: TokenMergePlan;
|
|
93
|
+
input: TokenMergeInput;
|
|
94
|
+
sets: {
|
|
95
|
+
base: TokenSet;
|
|
96
|
+
mine: TokenSet;
|
|
97
|
+
theirs: TokenSet;
|
|
98
|
+
};
|
|
99
|
+
/** Every token file of each side, relative to the tokens root. */
|
|
100
|
+
mineFiles: Record<string, string>;
|
|
101
|
+
theirsFiles: Record<string, string>;
|
|
102
|
+
pairs: ContrastPair[];
|
|
103
|
+
options: LayoutOptions;
|
|
104
|
+
};
|
|
105
|
+
/** What the commit needs: main's tip and its tree, the branch head tree and its own files. */
|
|
106
|
+
write?: {
|
|
107
|
+
mainSha: string;
|
|
108
|
+
mainTree: string;
|
|
109
|
+
headSha: string;
|
|
110
|
+
headTree: Map<string, TreeEntry>;
|
|
111
|
+
changeFiles: CompareFile[];
|
|
112
|
+
};
|
|
113
|
+
}
|
|
114
|
+
/**
|
|
115
|
+
* What conflicts and who resolves it. Reads the files main changed since the branch started (one compare), then, for
|
|
116
|
+
* a pure token-file conflict, the token files at the shared start, in the branch and in main. `tokensRoot` is the
|
|
117
|
+
* best guess before the config is read (Studio: its site config); `contrastFallback` the contrast checks to use when
|
|
118
|
+
* main has none.
|
|
119
|
+
*/
|
|
120
|
+
export declare function readLibraryConflicts(gh: GitHubClient, compare: LibraryCompare, headSha: string, opts?: {
|
|
121
|
+
tokensRoot?: string | undefined;
|
|
122
|
+
contrastFallback?: string | undefined;
|
|
123
|
+
}): Promise<LibraryConflicts>;
|
|
124
|
+
/**
|
|
125
|
+
* Every token file once resolved, relative to the tokens root: main's files, the branch's own token files where only
|
|
126
|
+
* the branch touched them, and the merged files where both did.
|
|
127
|
+
*/
|
|
128
|
+
export declare function resolvedTokenFiles(data: LibraryConflicts, choices: MergeChoices): {
|
|
129
|
+
all: Record<string, string>;
|
|
130
|
+
merged: Record<string, string | null>;
|
|
131
|
+
};
|
|
132
|
+
/**
|
|
133
|
+
* Commits the resolution to the branch: a merge commit of main and the branch, whose tree is main plus the branch's
|
|
134
|
+
* own files plus the merged token files. Fast-forward only: when the branch moved meanwhile, GitHub refuses and
|
|
135
|
+
* nothing is lost.
|
|
136
|
+
*/
|
|
137
|
+
export declare function commitLibraryResolution(gh: GitHubClient, pull: {
|
|
138
|
+
head: {
|
|
139
|
+
ref: string;
|
|
140
|
+
sha: string;
|
|
141
|
+
};
|
|
142
|
+
base: {
|
|
143
|
+
ref: string;
|
|
144
|
+
};
|
|
145
|
+
}, data: LibraryConflicts, choices: MergeChoices, who: string | null | undefined): Promise<string>;
|
|
@@ -3,6 +3,8 @@ import { buildTokenSet } from '../token-set';
|
|
|
3
3
|
export interface TokenInfo {
|
|
4
4
|
path: string;
|
|
5
5
|
type: string;
|
|
6
|
+
/** Durations and easings: the value in the default modes (`{ value: 150, unit: 'ms' }`, `[0.2, 0, 0, 1]`), for motion. */
|
|
7
|
+
value?: unknown;
|
|
6
8
|
}
|
|
7
9
|
export interface SpecGeneratorOptions {
|
|
8
10
|
/** Repo-relative components directory ("packages/react/src/components"). */
|
|
@@ -14,11 +16,39 @@ export interface SpecGeneratorOptions {
|
|
|
14
16
|
styleSuffix?: string | undefined;
|
|
15
17
|
/** Repo-relative ESM build of lucide-react ("node_modules/lucide-react/dist/esm"), for the icons section. */
|
|
16
18
|
lucideDir?: string | undefined;
|
|
19
|
+
/** Every component folder, to find components a file exports besides its own (Radio in RadioGroup.tsx). */
|
|
20
|
+
components?: string[] | undefined;
|
|
21
|
+
/** Repo-relative global stylesheet apps load before the components (inherited text styles, tag rules). */
|
|
22
|
+
baseCss?: string | undefined;
|
|
23
|
+
/** Repo-relative folder of specs drafted with Claude; default `component-spec-overrides` next to the specs file. */
|
|
24
|
+
overridesDir?: string | undefined;
|
|
17
25
|
}
|
|
18
26
|
/** "iconStart" -> "Icon start". */
|
|
19
27
|
export declare const sentenceCase: (prop: string) => string;
|
|
28
|
+
/**
|
|
29
|
+
* JSX text as React renders it (Babel's rule): lines trimmed where they meet a line break, empty lines dropped, the
|
|
30
|
+
* others joined with one space; spaces inside a line, and at the ends of a single line, are kept.
|
|
31
|
+
*/
|
|
32
|
+
export declare function jsxText(text: string): string;
|
|
33
|
+
/** Renders the main component for one set of axis values, with stable part ids. */
|
|
34
|
+
/**
|
|
35
|
+
* Which part of a component with a popup a set draws: the component without its popup (a select's trigger), or the
|
|
36
|
+
* popup alone drawn open (`*.Popup` under the `*.Portal`), the way a Figma UI kit draws menus and dialogs.
|
|
37
|
+
*/
|
|
38
|
+
export type SpecView = 'without-popup' | 'popup';
|
|
39
|
+
/**
|
|
40
|
+
* Why a component cannot be drawn faithfully: thrown by the generator, recorded in the coverage list as the reason
|
|
41
|
+
* ("opens a popup", "uses CSS grid"). The message is plain language for designers.
|
|
42
|
+
*/
|
|
43
|
+
export declare class UnsupportedComponentError extends Error {
|
|
44
|
+
component: string;
|
|
45
|
+
reason: string;
|
|
46
|
+
constructor(component: string, reason: string);
|
|
47
|
+
}
|
|
20
48
|
/** The spec of one component, or an error message when it cannot be derived. */
|
|
21
|
-
export declare function generateComponentSpec(name: string, opts: SpecGeneratorOptions): ComponentSpec;
|
|
49
|
+
export declare function generateComponentSpec(name: string, opts: SpecGeneratorOptions, view?: SpecView, setName?: string, fixed?: Record<string, string>): ComponentSpec;
|
|
50
|
+
/** Whether a spec draws anything: a fill, a border, an icon or a text of its own. Layout helpers draw nothing. */
|
|
51
|
+
export declare function specDrawsSomething(spec: ComponentSpec): boolean;
|
|
22
52
|
/** Icons every pulled file gets besides the ones the components use, so designers can swap without importing. */
|
|
23
53
|
export declare const COMMON_ICONS: string[];
|
|
24
54
|
/** The icon components themselves: Icon.tsx draws `sm` by default; Lucide's grid is 24, the `lg` size. */
|
|
@@ -32,16 +62,41 @@ export declare const MEDIA_SLOT: SpecSlot;
|
|
|
32
62
|
export declare function generateIcons(components: ComponentSpec[], opts: SpecGeneratorOptions, slots?: SpecSlot[]): SpecIcon[];
|
|
33
63
|
/** Content components the specs' slots swap to: each component's text slot (its default variant's text fields), then Media. */
|
|
34
64
|
export declare function generateSlots(components: ComponentSpec[]): SpecSlot[];
|
|
65
|
+
/** Specs of the named components (sets), in that order. Throws when one cannot be generated. */
|
|
35
66
|
export declare function generateComponentSpecs(names: string[], opts: SpecGeneratorOptions): ComponentSpecsFile;
|
|
36
|
-
/**
|
|
37
|
-
|
|
67
|
+
/**
|
|
68
|
+
* Every component folder, generated when the generator can draw it faithfully, else recorded with the reason it
|
|
69
|
+
* cannot (unsupported) or as a layout helper with no visual of its own. Support is decided here, from what the generator
|
|
70
|
+
* can read: no list to maintain. A folder's other exports (Radio in RadioGroup) get their own set when they draw
|
|
71
|
+
* something; exports drawn inside the main set (CardHeader) do not.
|
|
72
|
+
*/
|
|
73
|
+
export declare function generateAllComponentSpecs(folders: string[], opts: SpecGeneratorOptions): ComponentSpecsFile;
|
|
74
|
+
/** Where drafted specs live: next to component-specs.json (packages/react/component-spec-overrides). */
|
|
75
|
+
export declare const overridesDirOf: (componentsDir: string) => string;
|
|
76
|
+
/** FNV-1a of the code a drafted spec was read from, to tell when the code changed since. */
|
|
77
|
+
export declare function draftedCodeHash(files: string[], read: (path: string) => string | undefined): string;
|
|
78
|
+
/**
|
|
79
|
+
* A spec Claude drafted for a component the generator cannot read: `component-spec-overrides/<Folder>.json`, a
|
|
80
|
+
* ComponentSpec marked `"source": "drafted"` with the files it was read from (`files`), the generator's reason and the
|
|
81
|
+
* code's hash when drafted (`codeHash`). Validated like a generated spec, against the repo's tokens: an invalid one
|
|
82
|
+
* fails `npm run specs`. Never counted as generated: its coverage is `drafted`, and it is `stale` once the code changed.
|
|
83
|
+
*/
|
|
84
|
+
export declare function draftedSpec(folder: string, opts: SpecGeneratorOptions): ComponentSpec | undefined;
|
|
38
85
|
/** CSS custom property -> token, for every token of the repo (all tiers), with the repo's cssVar convention. */
|
|
39
86
|
export declare function tokenCssIndex(files: Record<string, string>, opts?: {
|
|
40
87
|
prefix?: string;
|
|
41
88
|
separator?: string;
|
|
42
89
|
layout?: Parameters<typeof buildTokenSet>[1];
|
|
43
90
|
}): Map<string, TokenInfo>;
|
|
44
|
-
/**
|
|
91
|
+
/** Generator options for the repo at `root` from bridge.config.json (tokens root, components dir, cssVar), and its component folders. */
|
|
92
|
+
export declare function repoSpecOptions(root: string): {
|
|
93
|
+
opts: SpecGeneratorOptions;
|
|
94
|
+
folders: string[];
|
|
95
|
+
};
|
|
96
|
+
/**
|
|
97
|
+
* Specs for the repo at `root`. With `names`, those sets only (throws when one cannot be generated). Without, every
|
|
98
|
+
* component folder: the sets the generator can draw, and the coverage of all of them (what `npm run specs` writes).
|
|
99
|
+
*/
|
|
45
100
|
export declare function generateRepoComponentSpecs(root: string, names?: string[]): ComponentSpecsFile;
|
|
46
101
|
/** The JSON text written to disk: stable, two-space indent, trailing newline. */
|
|
47
102
|
export declare const serializeComponentSpecs: (f: ComponentSpecsFile) => string;
|
package/dist/node/index.d.ts
CHANGED