delacour 0.1.0-alpha.5 → 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.
- package/README.md +6 -6
- package/dist/index.js +250 -53
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -5,7 +5,7 @@ repository — you own `button.tsx` and can edit it, rather than waiting for a
|
|
|
5
5
|
release.
|
|
6
6
|
|
|
7
7
|
```bash
|
|
8
|
-
bunx delacour@
|
|
8
|
+
bunx delacour@latest add button
|
|
9
9
|
```
|
|
10
10
|
|
|
11
11
|
That is the whole install. `add` sets the project up on its first run — config, Metro, the Tailwind
|
|
@@ -58,7 +58,7 @@ whether or not any are missing:
|
|
|
58
58
|
|
|
59
59
|
```txt
|
|
60
60
|
● Needs 14 external packages, 2 not here yet:
|
|
61
|
-
│ bunx expo install
|
|
61
|
+
│ bunx expo install react-native-teleport react-native-keyboard-controller
|
|
62
62
|
│ already installed — clsx, react-native-reanimated, react-native-svg, tailwind-variants, …
|
|
63
63
|
```
|
|
64
64
|
|
|
@@ -66,7 +66,7 @@ Then it asks. `--install` answers yes without asking, `--no-install` answers no,
|
|
|
66
66
|
nobody to ask — a script, CI, an agent — installs nothing and prints the commands instead:
|
|
67
67
|
|
|
68
68
|
```bash
|
|
69
|
-
bunx delacour@
|
|
69
|
+
bunx delacour@latest add bottom-sheet --install
|
|
70
70
|
```
|
|
71
71
|
|
|
72
72
|
The missing packages are shown as commands, not names, because the command is the part that is not
|
|
@@ -86,7 +86,7 @@ import { Button } from "@acme/ui/button";
|
|
|
86
86
|
```
|
|
87
87
|
|
|
88
88
|
```bash
|
|
89
|
-
bunx delacour@
|
|
89
|
+
bunx delacour@latest init --package-name @acme/ui --package-path packages/ui # no prompts
|
|
90
90
|
```
|
|
91
91
|
|
|
92
92
|
|
|
@@ -95,8 +95,8 @@ bunx delacour@alpha init --package-name @acme/ui --package-path packages/ui #
|
|
|
95
95
|
walking up from `--cwd`. In a monorepo that means:
|
|
96
96
|
|
|
97
97
|
```bash
|
|
98
|
-
cd packages/ui && bunx delacour@
|
|
99
|
-
cd apps/mobile && bunx delacour@
|
|
98
|
+
cd packages/ui && bunx delacour@latest init # shared package, several apps use it
|
|
99
|
+
cd apps/mobile && bunx delacour@latest init # straight into the app
|
|
100
100
|
```
|
|
101
101
|
|
|
102
102
|
Either way the CLI finds the Expo app and wires *its* Metro config and CSS
|
package/dist/index.js
CHANGED
|
@@ -10687,6 +10687,12 @@ const x = (command, args, userOptions) => {
|
|
|
10687
10687
|
};
|
|
10688
10688
|
const exec = x;
|
|
10689
10689
|
//#endregion
|
|
10690
|
+
//#region src/project/channel.ts
|
|
10691
|
+
function channelFor(version) {
|
|
10692
|
+
return /-alpha\b/.test(version) ? "alpha" : "latest";
|
|
10693
|
+
}
|
|
10694
|
+
const CLI_CHANNEL = channelFor("0.1.0");
|
|
10695
|
+
//#endregion
|
|
10690
10696
|
//#region src/project/package-manager.ts
|
|
10691
10697
|
const ADD = {
|
|
10692
10698
|
bun: ["bun", ["add"]],
|
|
@@ -10708,55 +10714,57 @@ const EXPO_RUNNER = {
|
|
|
10708
10714
|
npm: ["npx", ["expo", "install"]]
|
|
10709
10715
|
};
|
|
10710
10716
|
/**
|
|
10711
|
-
*
|
|
10717
|
+
* The packages this repository publishes, which follow the CLI's channel.
|
|
10712
10718
|
*
|
|
10713
|
-
*
|
|
10714
|
-
*
|
|
10715
|
-
*
|
|
10716
|
-
* on a Delacour package until `chart`.
|
|
10719
|
+
* On the alpha channel they are installed as `name@alpha`: the snapshot a
|
|
10720
|
+
* merge to `develop` published, not the last stable release `latest` serves.
|
|
10721
|
+
* Everything else is always installed untagged.
|
|
10717
10722
|
*
|
|
10718
10723
|
* Applied to the command's ARGS only, never to `packages`: `missingPackages`
|
|
10719
10724
|
* compares bare names against the project's own `package.json`, and a tagged
|
|
10720
10725
|
* spec there would never match anything and would reinstall on every run.
|
|
10721
|
-
*
|
|
10722
|
-
* Delete this map when `changeset pre exit` runs — see the root AGENTS.md.
|
|
10723
10726
|
*/
|
|
10724
|
-
const
|
|
10725
|
-
|
|
10726
|
-
|
|
10727
|
-
|
|
10728
|
-
|
|
10727
|
+
const DELACOUR_PACKAGES = /* @__PURE__ */ new Set([
|
|
10728
|
+
"@delacour/react-native-bottom-sheet",
|
|
10729
|
+
"@delacour/react-native-charts",
|
|
10730
|
+
"@delacour/react-native-ui"
|
|
10731
|
+
]);
|
|
10732
|
+
/** A package name with the dist-tag its channel pins, where it has one. */
|
|
10733
|
+
function toSpec(name, channel) {
|
|
10734
|
+
return channel === "alpha" && DELACOUR_PACKAGES.has(name) ? `${name}@alpha` : name;
|
|
10729
10735
|
}
|
|
10730
10736
|
/**
|
|
10731
10737
|
* The range a shared package declares for a peer it does not pin.
|
|
10732
10738
|
*
|
|
10733
|
-
* `*` is the usual answer, and it is wrong for a package
|
|
10734
|
-
*
|
|
10735
|
-
* `*` matches nothing `
|
|
10736
|
-
* peer as unmet and goes to the registry for a version that does
|
|
10737
|
-
* which is how `add` failed inside `expo install`, a step that
|
|
10738
|
-
* the package. `>=0.0.0-0`
|
|
10739
|
-
*
|
|
10739
|
+
* `*` is the usual answer, and it is wrong for a Delacour package: semver's
|
|
10740
|
+
* `*` admits no prerelease, so a peer on `@delacour/react-native-charts`
|
|
10741
|
+
* written as `*` matches nothing an `x.y.z-alpha.N` can ever satisfy. Bun then
|
|
10742
|
+
* treats the peer as unmet and goes to the registry for a version that does
|
|
10743
|
+
* not exist — which is how `add` failed inside `expo install`, a step that
|
|
10744
|
+
* never named the package. `>=0.0.0-0` admits every prerelease and every
|
|
10745
|
+
* stable version, so it holds on either channel.
|
|
10740
10746
|
*/
|
|
10741
10747
|
function peerRange(name) {
|
|
10742
|
-
return
|
|
10748
|
+
return DELACOUR_PACKAGES.has(name) ? ">=0.0.0-0" : "*";
|
|
10743
10749
|
}
|
|
10744
10750
|
function installCommands(request) {
|
|
10745
10751
|
const groups = [];
|
|
10752
|
+
const channel = request.channel ?? CLI_CHANNEL;
|
|
10753
|
+
const spec = (name) => toSpec(name, channel);
|
|
10746
10754
|
const [addCommand, addArgs] = ADD[request.packageManager];
|
|
10747
10755
|
if (request.expoDependencies.length > 0) {
|
|
10748
10756
|
const [command, args] = EXPO_RUNNER[request.packageManager];
|
|
10749
10757
|
groups.push({
|
|
10750
10758
|
label: "expo install",
|
|
10751
10759
|
command,
|
|
10752
|
-
args: [...args, ...request.expoDependencies.map(
|
|
10760
|
+
args: [...args, ...request.expoDependencies.map(spec)],
|
|
10753
10761
|
packages: [...request.expoDependencies]
|
|
10754
10762
|
});
|
|
10755
10763
|
}
|
|
10756
10764
|
if (request.dependencies.length > 0) groups.push({
|
|
10757
10765
|
label: `${addCommand} add`,
|
|
10758
10766
|
command: addCommand,
|
|
10759
|
-
args: [...addArgs, ...request.dependencies.map(
|
|
10767
|
+
args: [...addArgs, ...request.dependencies.map(spec)],
|
|
10760
10768
|
packages: [...request.dependencies]
|
|
10761
10769
|
});
|
|
10762
10770
|
if (request.devDependencies.length > 0) groups.push({
|
|
@@ -10765,7 +10773,7 @@ function installCommands(request) {
|
|
|
10765
10773
|
args: [
|
|
10766
10774
|
...addArgs,
|
|
10767
10775
|
DEV_FLAG[request.packageManager],
|
|
10768
|
-
...request.devDependencies.map(
|
|
10776
|
+
...request.devDependencies.map(spec)
|
|
10769
10777
|
],
|
|
10770
10778
|
packages: [...request.devDependencies]
|
|
10771
10779
|
});
|
|
@@ -10776,7 +10784,8 @@ function planDependencies(request, packageJson) {
|
|
|
10776
10784
|
packageManager: request.packageManager,
|
|
10777
10785
|
expoDependencies: missingPackages(packageJson, request.expoDependencies),
|
|
10778
10786
|
dependencies: missingPackages(packageJson, request.dependencies),
|
|
10779
|
-
devDependencies: missingPackages(packageJson, request.devDependencies)
|
|
10787
|
+
devDependencies: missingPackages(packageJson, request.devDependencies),
|
|
10788
|
+
channel: request.channel
|
|
10780
10789
|
});
|
|
10781
10790
|
const wanted = unique([
|
|
10782
10791
|
...request.expoDependencies,
|
|
@@ -11219,8 +11228,9 @@ const registryIndexSchema = object$1({
|
|
|
11219
11228
|
* `raw.githubusercontent.com`, so there is nothing to host and nothing to keep
|
|
11220
11229
|
* running. The cost is that a ref has to be chosen: the CLI is published with
|
|
11221
11230
|
* the tag it was built from baked in, so a given version always reads the
|
|
11222
|
-
* registry it shipped against, and `--ref
|
|
11223
|
-
* since.
|
|
11231
|
+
* registry it shipped against, and `--ref develop` opts into whatever has
|
|
11232
|
+
* landed since. `main` is the last release, so `--ref main` only catches up to
|
|
11233
|
+
* the newest published CLI.
|
|
11224
11234
|
*
|
|
11225
11235
|
* That a ref pins the whole registry is also what makes it safe to split an
|
|
11226
11236
|
* item across several documents: `r/button.json` and the files it names are
|
|
@@ -11237,13 +11247,13 @@ const DEFAULT_REGISTRY_URL = "https://raw.githubusercontent.com/delacournz/delac
|
|
|
11237
11247
|
* Replaced at build time with the git tag being published (see `tsdown.config.ts`).
|
|
11238
11248
|
* `main` in a working tree, where there is no tag yet.
|
|
11239
11249
|
*/
|
|
11240
|
-
const DEFAULT_REGISTRY_REF = "
|
|
11250
|
+
const DEFAULT_REGISTRY_REF = "8270767a831685e2008e0465214c3471f63e5187";
|
|
11241
11251
|
const RAW_GITHUB = "https://raw.githubusercontent.com";
|
|
11242
11252
|
const GITHUB_SHORTHAND = /^github:([^/#]+)\/([^/#]+)(?:#(.+))?$/;
|
|
11243
11253
|
/** `https://raw.githubusercontent.com/owner/repo` and nothing more. */
|
|
11244
11254
|
const BARE_RAW_REPO = new RegExp(`^${RAW_GITHUB}/([^/]+)/([^/]+)$`);
|
|
11245
11255
|
function resolveRegistrySource(options) {
|
|
11246
|
-
const ref = options.ref || "
|
|
11256
|
+
const ref = options.ref || "8270767a831685e2008e0465214c3471f63e5187";
|
|
11247
11257
|
const url = options.url?.trim();
|
|
11248
11258
|
if (!url) return remote(`${DEFAULT_REGISTRY_URL}/${ref}`);
|
|
11249
11259
|
const shorthand = GITHUB_SHORTHAND.exec(url);
|
|
@@ -11483,7 +11493,7 @@ var UnknownItemError = class extends Error {
|
|
|
11483
11493
|
item;
|
|
11484
11494
|
requiredBy;
|
|
11485
11495
|
constructor(item, requiredBy) {
|
|
11486
|
-
super(requiredBy ? `"${item}" is not in the registry, and is required by "${requiredBy}". The registry may be newer than this CLI — try \`--ref
|
|
11496
|
+
super(requiredBy ? `"${item}" is not in the registry, and is required by "${requiredBy}". The registry may be newer than this CLI — try \`--ref develop\`.` : `"${item}" is not in the registry. Run \`delacour list\` to see what is available.`);
|
|
11487
11497
|
this.item = item;
|
|
11488
11498
|
this.requiredBy = requiredBy;
|
|
11489
11499
|
this.name = "UnknownItemError";
|
|
@@ -11829,9 +11839,11 @@ const PINNED_MODULES = [
|
|
|
11829
11839
|
"react",
|
|
11830
11840
|
"react-native",
|
|
11831
11841
|
"react-native-gesture-handler",
|
|
11842
|
+
"react-native-keyboard-controller",
|
|
11832
11843
|
"react-native-reanimated",
|
|
11833
11844
|
"react-native-safe-area-context",
|
|
11834
11845
|
"react-native-svg",
|
|
11846
|
+
"react-native-teleport",
|
|
11835
11847
|
"react-native-worklets"
|
|
11836
11848
|
];
|
|
11837
11849
|
const REQUIRE = "const { withUniwindConfig } = require(\"uniwind/metro\");";
|
|
@@ -12079,7 +12091,10 @@ function geometry({ radius, heights, text, icons, navbar, gutter, buttonRadius }
|
|
|
12079
12091
|
"spacing-screen-gutter": gutter,
|
|
12080
12092
|
"spacing-chart-sm": chartHeight(LIBRARY_CHART[0], heights[1]),
|
|
12081
12093
|
"spacing-chart-md": chartHeight(LIBRARY_CHART[1], heights[1]),
|
|
12082
|
-
"spacing-chart-lg": chartHeight(LIBRARY_CHART[2], heights[1])
|
|
12094
|
+
"spacing-chart-lg": chartHeight(LIBRARY_CHART[2], heights[1]),
|
|
12095
|
+
"spacing-fab-sm": LIBRARY_FAB[0],
|
|
12096
|
+
"spacing-fab-md": LIBRARY_FAB[1],
|
|
12097
|
+
"spacing-fab-lg": LIBRARY_FAB[2]
|
|
12083
12098
|
};
|
|
12084
12099
|
}
|
|
12085
12100
|
const LIBRARY_HEIGHTS = [
|
|
@@ -12111,6 +12126,17 @@ const LIBRARY_CHART = [
|
|
|
12111
12126
|
280
|
|
12112
12127
|
];
|
|
12113
12128
|
/**
|
|
12129
|
+
* A floating action button's footprint, the same under every style. It floats
|
|
12130
|
+
* over content rather than sitting in a row of controls, so a denser style's
|
|
12131
|
+
* shorter buttons are no reason to shrink the one target above the list — and
|
|
12132
|
+
* 44 is the floor a touch target cannot go under.
|
|
12133
|
+
*/
|
|
12134
|
+
const LIBRARY_FAB = [
|
|
12135
|
+
44,
|
|
12136
|
+
56,
|
|
12137
|
+
64
|
|
12138
|
+
];
|
|
12139
|
+
/**
|
|
12114
12140
|
* A chart's height, scaled to a style's control density.
|
|
12115
12141
|
*
|
|
12116
12142
|
* A plot is a region rather than a control, so none of the axes a style
|
|
@@ -12335,7 +12361,10 @@ const GEOMETRY_NAMES = new Set([
|
|
|
12335
12361
|
"spacing-screen-gutter",
|
|
12336
12362
|
"spacing-chart-sm",
|
|
12337
12363
|
"spacing-chart-md",
|
|
12338
|
-
"spacing-chart-lg"
|
|
12364
|
+
"spacing-chart-lg",
|
|
12365
|
+
"spacing-fab-sm",
|
|
12366
|
+
"spacing-fab-md",
|
|
12367
|
+
"spacing-fab-lg"
|
|
12339
12368
|
].map((token) => `--${token}`));
|
|
12340
12369
|
/** Steps of the corner scale `tokens.css` derives from `--radius` on its own. */
|
|
12341
12370
|
const DERIVED_RADIUS = /^--radius-(xs|sm|md|lg|xl|2xl|3xl|4xl|full)$/;
|
|
@@ -12888,10 +12917,11 @@ function checkFramework(project) {
|
|
|
12888
12917
|
};
|
|
12889
12918
|
}
|
|
12890
12919
|
/**
|
|
12891
|
-
* Reanimated 4 is New Architecture only.
|
|
12920
|
+
* Reanimated 4 is New Architecture only, and so is the bottom sheet's portal.
|
|
12892
12921
|
*
|
|
12893
|
-
* On the old architecture
|
|
12894
|
-
* pressable in the library runs one.
|
|
12922
|
+
* On the old architecture Reanimated fails at build or at the first worklet,
|
|
12923
|
+
* and every pressable in the library runs one. `react-native-teleport`, which
|
|
12924
|
+
* `BottomSheet` teleports through, ships a Fabric view and nothing else.
|
|
12895
12925
|
*/
|
|
12896
12926
|
function checkNewArchitecture(expoConfig, project) {
|
|
12897
12927
|
if (!expoConfig) return {
|
|
@@ -12910,7 +12940,7 @@ function checkNewArchitecture(expoConfig, project) {
|
|
|
12910
12940
|
name: "New Architecture",
|
|
12911
12941
|
status: "fail",
|
|
12912
12942
|
detail: "disabled",
|
|
12913
|
-
fix: "Set \"newArchEnabled\": true — Reanimated 4 does not run without it."
|
|
12943
|
+
fix: "Set \"newArchEnabled\": true — Reanimated 4 does not run without it, and BottomSheet needs the new architecture for its portal."
|
|
12914
12944
|
};
|
|
12915
12945
|
}
|
|
12916
12946
|
/**
|
|
@@ -13386,7 +13416,9 @@ async function checkDuplicateNativeModules(project) {
|
|
|
13386
13416
|
"react-native",
|
|
13387
13417
|
"react-native-reanimated",
|
|
13388
13418
|
"react-native-gesture-handler",
|
|
13389
|
-
"react-native-
|
|
13419
|
+
"react-native-keyboard-controller",
|
|
13420
|
+
"react-native-svg",
|
|
13421
|
+
"react-native-teleport"
|
|
13390
13422
|
].filter((name) => existsSync(join(project.appRoot, "node_modules", name)) && existsSync(join(project.workspaceRoot, "node_modules", name)));
|
|
13391
13423
|
if (duplicated.length === 0) return {
|
|
13392
13424
|
name: "Native modules",
|
|
@@ -13878,7 +13910,7 @@ function report$1(written, planned, requested, output) {
|
|
|
13878
13910
|
* What these components need from npm, printed every time.
|
|
13879
13911
|
*
|
|
13880
13912
|
* Every time, including the run where nothing is missing. A component that
|
|
13881
|
-
* needs
|
|
13913
|
+
* needs `react-native-teleport` and got it three components ago is not the same
|
|
13882
13914
|
* thing as a component that needs nothing, and a reader who sees no block at
|
|
13883
13915
|
* all cannot tell which they are looking at.
|
|
13884
13916
|
*
|
|
@@ -30091,6 +30123,16 @@ const COMPONENTS = [
|
|
|
30091
30123
|
title: "Accordion",
|
|
30092
30124
|
description: "Collapsible sections whose panels animate to their measured height."
|
|
30093
30125
|
},
|
|
30126
|
+
{
|
|
30127
|
+
name: "alert",
|
|
30128
|
+
title: "Alert",
|
|
30129
|
+
description: "A status message with a glyph picked from its status, a title, a description and an optional action."
|
|
30130
|
+
},
|
|
30131
|
+
{
|
|
30132
|
+
name: "avatar",
|
|
30133
|
+
title: "Avatar",
|
|
30134
|
+
description: "A person as a picture, with an initials fallback, a corner badge and an overlapping group."
|
|
30135
|
+
},
|
|
30094
30136
|
{
|
|
30095
30137
|
name: "badge",
|
|
30096
30138
|
title: "Badge",
|
|
@@ -30099,13 +30141,23 @@ const COMPONENTS = [
|
|
|
30099
30141
|
{
|
|
30100
30142
|
name: "bottom-sheet",
|
|
30101
30143
|
title: "Bottom Sheet",
|
|
30102
|
-
description: "A draggable sheet over the screen, on @
|
|
30144
|
+
description: "A draggable sheet over the screen: snap points, keyboard, sticky footer, scrollables, steps and a teleported portal, on @delacour/react-native-bottom-sheet."
|
|
30103
30145
|
},
|
|
30104
30146
|
{
|
|
30105
30147
|
name: "button",
|
|
30106
30148
|
title: "Button",
|
|
30107
30149
|
description: "A pressable action composed from parts, with variants, sizes and a loading state."
|
|
30108
30150
|
},
|
|
30151
|
+
{
|
|
30152
|
+
name: "calendar",
|
|
30153
|
+
title: "Calendar",
|
|
30154
|
+
description: "A month grid for picking a day, several days or a range, with swipe paging and month and year jump views."
|
|
30155
|
+
},
|
|
30156
|
+
{
|
|
30157
|
+
name: "card",
|
|
30158
|
+
title: "Card",
|
|
30159
|
+
description: "A content surface with a header, a body and a footer, built on Surface."
|
|
30160
|
+
},
|
|
30109
30161
|
{
|
|
30110
30162
|
name: "chart",
|
|
30111
30163
|
title: "Chart",
|
|
@@ -30116,6 +30168,46 @@ const COMPONENTS = [
|
|
|
30116
30168
|
title: "Checkbox",
|
|
30117
30169
|
description: "A checkbox with an indeterminate state, and a group that owns the selection."
|
|
30118
30170
|
},
|
|
30171
|
+
{
|
|
30172
|
+
name: "chip",
|
|
30173
|
+
title: "Chip",
|
|
30174
|
+
description: "An interactive pill: a filter that toggles, a tag, or a token with a remove control."
|
|
30175
|
+
},
|
|
30176
|
+
{
|
|
30177
|
+
name: "collapsible",
|
|
30178
|
+
title: "Collapsible",
|
|
30179
|
+
description: "One section shown and hidden by its own trigger, animated to its measured height."
|
|
30180
|
+
},
|
|
30181
|
+
{
|
|
30182
|
+
name: "context-menu",
|
|
30183
|
+
title: "Context Menu",
|
|
30184
|
+
description: "The actions that belong to a piece of content, reached by holding it — Menu's rows over a scrim, with a lifted preview."
|
|
30185
|
+
},
|
|
30186
|
+
{
|
|
30187
|
+
name: "dialog",
|
|
30188
|
+
title: "Dialog",
|
|
30189
|
+
description: "A centred card over a dimmed app that asks for a decision or a short input: confirm, alert dialog, form, with keyboard lift and focus handling."
|
|
30190
|
+
},
|
|
30191
|
+
{
|
|
30192
|
+
name: "drawer",
|
|
30193
|
+
title: "Drawer",
|
|
30194
|
+
description: "A panel that slides in from an edge and covers the app until dismissed: a navigation menu, a filter panel, a notifications tray, with swipe-to-dismiss and RTL-aware sides."
|
|
30195
|
+
},
|
|
30196
|
+
{
|
|
30197
|
+
name: "empty-state",
|
|
30198
|
+
title: "Empty State",
|
|
30199
|
+
description: "A placeholder for a list or screen with nothing in it: media, title, description and actions."
|
|
30200
|
+
},
|
|
30201
|
+
{
|
|
30202
|
+
name: "fab",
|
|
30203
|
+
title: "Fab",
|
|
30204
|
+
description: "A floating action button, extended with a label or unfolding a dial of related actions."
|
|
30205
|
+
},
|
|
30206
|
+
{
|
|
30207
|
+
name: "feedback",
|
|
30208
|
+
title: "Feedback",
|
|
30209
|
+
description: "A dialog for writing: the field in a recessed well, a send that waits on a promise, a draft kept across close, and steps that ease between heights."
|
|
30210
|
+
},
|
|
30119
30211
|
{
|
|
30120
30212
|
name: "field",
|
|
30121
30213
|
title: "Field",
|
|
@@ -30131,16 +30223,61 @@ const COMPONENTS = [
|
|
|
30131
30223
|
title: "Input",
|
|
30132
30224
|
description: "A text field, with a group that puts a prefix or suffix inside its border."
|
|
30133
30225
|
},
|
|
30226
|
+
{
|
|
30227
|
+
name: "item",
|
|
30228
|
+
title: "Item",
|
|
30229
|
+
description: "A row of media, text and actions for lists and settings, standalone or as a List Group row."
|
|
30230
|
+
},
|
|
30231
|
+
{
|
|
30232
|
+
name: "kpi",
|
|
30233
|
+
title: "Kpi",
|
|
30234
|
+
description: "One number, its change coloured by what it means, and a sparkline of how it got there, built on Card."
|
|
30235
|
+
},
|
|
30236
|
+
{
|
|
30237
|
+
name: "label",
|
|
30238
|
+
title: "Label",
|
|
30239
|
+
description: "A form control's name, with required, invalid and disabled states."
|
|
30240
|
+
},
|
|
30134
30241
|
{
|
|
30135
30242
|
name: "list-group",
|
|
30136
30243
|
title: "List Group",
|
|
30137
30244
|
description: "A surface grouping related rows, with dividers inserted automatically."
|
|
30138
30245
|
},
|
|
30246
|
+
{
|
|
30247
|
+
name: "menu",
|
|
30248
|
+
title: "Menu",
|
|
30249
|
+
description: "A list of actions anchored to the control that opens it — checkbox and radio rows, in-place submenus."
|
|
30250
|
+
},
|
|
30251
|
+
{
|
|
30252
|
+
name: "meter",
|
|
30253
|
+
title: "Meter",
|
|
30254
|
+
description: "A measurement on a fixed scale, coloured by where it falls — by regions, thresholds or whole blocks."
|
|
30255
|
+
},
|
|
30256
|
+
{
|
|
30257
|
+
name: "overlay",
|
|
30258
|
+
title: "Overlay",
|
|
30259
|
+
description: "The provider, teleported portal, scrim, presence lifecycle and back-button handling every dialog, drawer, popover, tooltip and toast is drawn with."
|
|
30260
|
+
},
|
|
30261
|
+
{
|
|
30262
|
+
name: "popover",
|
|
30263
|
+
title: "Popover",
|
|
30264
|
+
description: "A small panel anchored to its trigger that flips and shifts to stay on screen, with an arrow, a title, a close control and an optional scrim."
|
|
30265
|
+
},
|
|
30139
30266
|
{
|
|
30140
30267
|
name: "pressable",
|
|
30141
30268
|
title: "Pressable",
|
|
30142
30269
|
description: "The Gesture API press primitive: scale and fade feedback, haptics, disabled and busy states."
|
|
30143
30270
|
},
|
|
30271
|
+
{
|
|
30272
|
+
name: "progress",
|
|
30273
|
+
title: "Progress",
|
|
30274
|
+
description: "A bar showing how far a task has got, or a looping segment while it is under way."
|
|
30275
|
+
},
|
|
30276
|
+
{
|
|
30277
|
+
name: "progress-button",
|
|
30278
|
+
title: "Progress Button",
|
|
30279
|
+
description: "A button held to confirm: a fill grows while it is held and the action fires when it reaches the end."
|
|
30280
|
+
},
|
|
30144
30281
|
{
|
|
30145
30282
|
name: "provider",
|
|
30146
30283
|
title: "Provider",
|
|
@@ -30151,16 +30288,36 @@ const COMPONENTS = [
|
|
|
30151
30288
|
title: "Radio",
|
|
30152
30289
|
description: "A radio and the group that owns which one is selected."
|
|
30153
30290
|
},
|
|
30291
|
+
{
|
|
30292
|
+
name: "rating",
|
|
30293
|
+
title: "Rating",
|
|
30294
|
+
description: "A row of stars that reads or sets a score, by tap or by drag, in whole or half steps."
|
|
30295
|
+
},
|
|
30154
30296
|
{
|
|
30155
30297
|
name: "screen",
|
|
30156
30298
|
title: "Screen",
|
|
30157
30299
|
description: "A screen frame: pinned chrome, a content region, and whatever scrolls between them."
|
|
30158
30300
|
},
|
|
30301
|
+
{
|
|
30302
|
+
name: "selection-mode",
|
|
30303
|
+
title: "Selection Mode",
|
|
30304
|
+
description: "Pick several things at once — a long press enters the mode — then act on them from a bar, in a list, a grid or a strip."
|
|
30305
|
+
},
|
|
30159
30306
|
{
|
|
30160
30307
|
name: "separator",
|
|
30161
30308
|
title: "Separator",
|
|
30162
30309
|
description: "A one-pixel rule, hidden from assistive technology."
|
|
30163
30310
|
},
|
|
30311
|
+
{
|
|
30312
|
+
name: "skeleton",
|
|
30313
|
+
title: "Skeleton",
|
|
30314
|
+
description: "A placeholder that shimmers or pulses while content loads, in step across a group."
|
|
30315
|
+
},
|
|
30316
|
+
{
|
|
30317
|
+
name: "slide-button",
|
|
30318
|
+
title: "Slide Button",
|
|
30319
|
+
description: "A handle dragged across a rail to confirm an action a tap should not reach."
|
|
30320
|
+
},
|
|
30164
30321
|
{
|
|
30165
30322
|
name: "slider",
|
|
30166
30323
|
title: "Slider",
|
|
@@ -30171,6 +30328,26 @@ const COMPONENTS = [
|
|
|
30171
30328
|
title: "Spinner",
|
|
30172
30329
|
description: "An animated loading indicator drawn on the icon scale."
|
|
30173
30330
|
},
|
|
30331
|
+
{
|
|
30332
|
+
name: "stack-card",
|
|
30333
|
+
title: "Stack Card",
|
|
30334
|
+
description: "A deck taken one card at a time by throwing the top one off, with stamps, undo and a decline."
|
|
30335
|
+
},
|
|
30336
|
+
{
|
|
30337
|
+
name: "steps",
|
|
30338
|
+
title: "Steps",
|
|
30339
|
+
description: "A stepper for multi-step flows: completed, current and upcoming steps joined by a line."
|
|
30340
|
+
},
|
|
30341
|
+
{
|
|
30342
|
+
name: "surface",
|
|
30343
|
+
title: "Surface",
|
|
30344
|
+
description: "A rounded container on the theme's fill ladder, stepping to the next fill as it nests."
|
|
30345
|
+
},
|
|
30346
|
+
{
|
|
30347
|
+
name: "swipe",
|
|
30348
|
+
title: "Swipe",
|
|
30349
|
+
description: "A row that slides aside to reveal actions behind it, with a full swipe and a group that keeps one open."
|
|
30350
|
+
},
|
|
30174
30351
|
{
|
|
30175
30352
|
name: "switch",
|
|
30176
30353
|
title: "Switch",
|
|
@@ -30185,6 +30362,26 @@ const COMPONENTS = [
|
|
|
30185
30362
|
name: "text",
|
|
30186
30363
|
title: "Text",
|
|
30187
30364
|
description: "Typography: the type scale, weights and the page-level colours."
|
|
30365
|
+
},
|
|
30366
|
+
{
|
|
30367
|
+
name: "textarea",
|
|
30368
|
+
title: "Textarea",
|
|
30369
|
+
description: "A multiline text field sized in rows, with auto-grow and a character count."
|
|
30370
|
+
},
|
|
30371
|
+
{
|
|
30372
|
+
name: "toast",
|
|
30373
|
+
title: "Toast",
|
|
30374
|
+
description: "A brief message shown from anywhere, even outside React: stacked at an edge, swiped away, paused while touched, with a promise form and Alert's statuses."
|
|
30375
|
+
},
|
|
30376
|
+
{
|
|
30377
|
+
name: "toggle-button",
|
|
30378
|
+
title: "Toggle Button",
|
|
30379
|
+
description: "A button that stays pressed, alone or in a group with single or multiple selection."
|
|
30380
|
+
},
|
|
30381
|
+
{
|
|
30382
|
+
name: "tooltip",
|
|
30383
|
+
title: "Tooltip",
|
|
30384
|
+
description: "A short label on a long press, anchored to its control: hides itself, lets an outside tap through, and reads to a screen reader on the trigger."
|
|
30188
30385
|
}
|
|
30189
30386
|
];
|
|
30190
30387
|
//#endregion
|
|
@@ -30235,10 +30432,10 @@ Run them with the project's package manager — \`bunx\`, \`npx\`, \`pnpm dlx\`
|
|
|
30235
30432
|
|
|
30236
30433
|
| You need | Run |
|
|
30237
30434
|
| --- | --- |
|
|
30238
|
-
| what exists, and what each one is for | \`bunx delacour@
|
|
30239
|
-
| one component's files, props, closure and packages | \`bunx delacour@
|
|
30240
|
-
| to add one | \`bunx delacour@
|
|
30241
|
-
| to find out why something renders wrong with no error | \`bunx delacour@
|
|
30435
|
+
| what exists, and what each one is for | \`bunx delacour@latest list\` |
|
|
30436
|
+
| one component's files, props, closure and packages | \`bunx delacour@latest view <name>\` |
|
|
30437
|
+
| to add one | \`bunx delacour@latest add <name>\` |
|
|
30438
|
+
| to find out why something renders wrong with no error | \`bunx delacour@latest doctor\` |
|
|
30242
30439
|
|
|
30243
30440
|
**Always \`list\` before writing any React Native UI in this project.** A component that exists here
|
|
30244
30441
|
should be added, never reimplemented.
|
|
@@ -30248,7 +30445,7 @@ Uniwind's transform, points Tailwind at where the components landed, and copies
|
|
|
30248
30445
|
root provider in. There is no separate setup step to run first.
|
|
30249
30446
|
|
|
30250
30447
|
\`\`\`bash
|
|
30251
|
-
bunx delacour@
|
|
30448
|
+
bunx delacour@latest add button input field
|
|
30252
30449
|
\`\`\`
|
|
30253
30450
|
|
|
30254
30451
|
It prints what the components need from npm and **installs nothing** unless told to. Add
|
|
@@ -30259,7 +30456,7 @@ If the layout is not the default — a monorepo where the components belong to a
|
|
|
30259
30456
|
source directory this project does not call \`src\` — run \`init\` deliberately instead:
|
|
30260
30457
|
|
|
30261
30458
|
\`\`\`bash
|
|
30262
|
-
bunx delacour@
|
|
30459
|
+
bunx delacour@latest init --src app --package-name @acme/ui --package-path packages/ui
|
|
30263
30460
|
\`\`\`
|
|
30264
30461
|
|
|
30265
30462
|
## Six things that fail silently
|
|
@@ -30338,7 +30535,7 @@ The palette is one file, \`styles/theme.css\`, in Uniwind's \`@variant light\` /
|
|
|
30338
30535
|
shape. Two ways to change it, and neither is editing a component:
|
|
30339
30536
|
|
|
30340
30537
|
- build one at <https://ui.delacour.co.nz/theme> and paste the \`theme.css\` tab over the file;
|
|
30341
|
-
- bring a web app's across — \`bunx delacour@
|
|
30538
|
+
- bring a web app's across — \`bunx delacour@latest theme ./globals.css\` converts it in place.
|
|
30342
30539
|
|
|
30343
30540
|
A literal \`.dark { … }\` block is the trap. Uniwind registers it as a **utility class named \`dark\`**
|
|
30344
30541
|
that contributes nothing — no error, and a dark theme that never arrives. That is what \`theme\`
|
|
@@ -30354,7 +30551,7 @@ converts, and what \`doctor\` fails on.
|
|
|
30354
30551
|
| composition, sizing, tokens, styling | \`references/rules.md\` beside this file |
|
|
30355
30552
|
| something rendering wrong | \`references/troubleshooting.md\` beside this file |
|
|
30356
30553
|
|
|
30357
|
-
There is also an MCP server — \`bunx delacour@
|
|
30554
|
+
There is also an MCP server — \`bunx delacour@latest mcp\` — which exposes \`list_components\`,
|
|
30358
30555
|
\`get_component\`, \`add_components\`, \`init_project\` and \`check_project\` as tools. Prefer it when the
|
|
30359
30556
|
host supports MCP; the commands above are the same functions and need nothing installed.
|
|
30360
30557
|
`
|
|
@@ -30490,7 +30687,7 @@ runtime, \`--radius-md\` does not, so anything computing a corner applies the mu
|
|
|
30490
30687
|
path: "references/troubleshooting.md",
|
|
30491
30688
|
content: `# Delacour UI — symptom to cause
|
|
30492
30689
|
|
|
30493
|
-
Run \`bunx delacour@
|
|
30690
|
+
Run \`bunx delacour@latest doctor\` first. Every symptom below is configuration, produces no error of
|
|
30494
30691
|
its own, and \`doctor\` names the file and the fix for nine of them. Changing component code before
|
|
30495
30692
|
running it is how an afternoon goes.
|
|
30496
30693
|
|
|
@@ -30499,14 +30696,14 @@ running it is how an afternoon goes.
|
|
|
30499
30696
|
| Components render, but unstyled | Nothing imports the CSS entry, or the import is not the **first** statement of the root layout |
|
|
30500
30697
|
| Styled in dev, unstyled in a release build | Tailwind's \`@source\` globs do not cover where the components landed — the scanner does not follow a monorepo's symlink, so the glob must be a real path |
|
|
30501
30698
|
| Some classes work, others do nothing | \`withUniwindConfig\` is present but not the **outermost** Metro wrapper; an outer wrapper replaced the transformer |
|
|
30502
|
-
| Light works, dark never arrives | \`theme.css\` has a literal \`.dark { … }\` block. Run \`bunx delacour@
|
|
30699
|
+
| Light works, dark never arrives | \`theme.css\` has a literal \`.dark { … }\` block. Run \`bunx delacour@latest theme\` to convert it |
|
|
30503
30700
|
| Classes resolve oddly, or the build fails naming no library | NativeWind is installed. It compiles \`className\` and wraps Metro too, and two Tailwind transforms cannot share one Metro config — move across with [Uniwind's migration guide](https://docs.uniwind.dev/migration-from-nativewind) |
|
|
30504
30701
|
| Presses do nothing | No \`GestureHandlerRootView\` above the component — mount \`DelacourProvider\` at the root |
|
|
30505
30702
|
| \`Unable to resolve "@/components/ui/button"\` | \`experiments.tsconfigPaths\` is not \`true\` in the Expo config; Metro ignores tsconfig paths without it |
|
|
30506
30703
|
| A red box naming a module you just installed | A native module needs a rebuilt dev client. \`npx expo run:ios\` — a JS reload will not pick it up |
|
|
30507
30704
|
| Every \`className\` is a type error | \`uniwind-env.d.ts\` is not inside the app's own \`tsconfig\` include. It is one triple-slash reference and only works from there |
|
|
30508
30705
|
| \`Ref<never>\`, or two copies of React Native's types | Two realpaths for one package. A Bun workspace needs \`linker = "hoisted"\` in \`bunfig.toml\` |
|
|
30509
|
-
| \`add\` overwrote something you had edited | A file that differs is a conflict and \`add\` asks; \`--overwrite\` answers yes. \`bunx delacour@
|
|
30706
|
+
| \`add\` overwrote something you had edited | A file that differs is a conflict and \`add\` asks; \`--overwrite\` answers yes. \`bunx delacour@latest diff <name>\` shows what upstream changed |
|
|
30510
30707
|
| A component on the docs site is not in the registry | The published CLI reads the registry at the commit it shipped against. \`--ref main\` opts into what has landed since |
|
|
30511
30708
|
|
|
30512
30709
|
## What \`doctor\` checks
|
|
@@ -30517,9 +30714,9 @@ actually imports the CSS entry · New Architecture · path aliases and \`tsconfi
|
|
|
30517
30714
|
copies of a native module.
|
|
30518
30715
|
|
|
30519
30716
|
\`\`\`bash
|
|
30520
|
-
bunx delacour@
|
|
30521
|
-
bunx delacour@
|
|
30522
|
-
bunx delacour@
|
|
30717
|
+
bunx delacour@latest doctor # a report, with a fix per failure
|
|
30718
|
+
bunx delacour@latest doctor --json # the same, for a tool to read
|
|
30719
|
+
bunx delacour@latest info # the resolved config, and what was detected
|
|
30523
30720
|
\`\`\`
|
|
30524
30721
|
|
|
30525
30722
|
## When none of it fits
|
|
@@ -30756,7 +30953,7 @@ function report(result, output) {
|
|
|
30756
30953
|
if (result.derived.length > 0) output.info(`${result.derived.length} filled in, derived from tokens the theme does define: ${result.derived.map((name) => name.slice(2)).join(", ")}.`);
|
|
30757
30954
|
for (const warning of result.warnings) output.warn(warning);
|
|
30758
30955
|
}
|
|
30759
|
-
const program = new Command().name("delacour").description("Add React Native components to your Expo app. You own the code.").version("0.1.0
|
|
30956
|
+
const program = new Command().name("delacour").description("Add React Native components to your Expo app. You own the code.").version("0.1.0");
|
|
30760
30957
|
/** Shared by every command that reads the registry. */
|
|
30761
30958
|
function withRegistryOptions(command) {
|
|
30762
30959
|
return command.addOption(new Option("--registry <url>", "registry to read from: a URL, github:owner/repo, or a local path")).addOption(new Option("--ref <ref>", "git ref to read the registry at").default(DEFAULT_REGISTRY_REF)).addOption(new Option("--offline", "use only what is already cached")).addOption(new Option("-c, --cwd <path>", "directory to work in").default(process.cwd()));
|