@multiplatform.one/forms 6.4.0 → 6.4.2
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/dist/cjs/fields/DatePicker/Calendar.cjs +1 -1
- package/dist/cjs/fields/DatePicker/Calendar.native.js +1 -1
- package/dist/cjs/fields/DatePicker/DateRangePicker.cjs +1 -1
- package/dist/cjs/fields/DatePicker/DateRangePicker.native.js +1 -1
- package/dist/cjs/fields/DatePicker/DatetimePicker.cjs +1 -1
- package/dist/cjs/fields/DatePicker/DatetimePicker.native.js +1 -1
- package/dist/cjs/fields/DatePicker/DatetimePicker.native.js.map +1 -1
- package/dist/cjs/fields/DatePicker/MultiDatePicker.cjs +1 -1
- package/dist/cjs/fields/DatePicker/MultiDatePicker.native.js +1 -1
- package/dist/cjs/fields/DatePicker/index.cjs +1 -1
- package/dist/cjs/fields/DatePicker/index.native.js +1 -1
- package/dist/cjs/fields/Progress/index.cjs +23 -1
- package/dist/cjs/fields/Progress/index.native.js +24 -1
- package/dist/cjs/fields/Progress/index.native.js.map +1 -1
- package/dist/esm/fields/DatePicker/Calendar.mjs +1 -1
- package/dist/esm/fields/DatePicker/Calendar.native.js +1 -1
- package/dist/esm/fields/DatePicker/Calendar.native.js.map +1 -1
- package/dist/esm/fields/DatePicker/DateRangePicker.mjs +1 -1
- package/dist/esm/fields/DatePicker/DateRangePicker.native.js +1 -1
- package/dist/esm/fields/DatePicker/DateRangePicker.native.js.map +1 -1
- package/dist/esm/fields/DatePicker/DatetimePicker.mjs +1 -1
- package/dist/esm/fields/DatePicker/DatetimePicker.native.js +1 -1
- package/dist/esm/fields/DatePicker/MultiDatePicker.mjs +1 -1
- package/dist/esm/fields/DatePicker/MultiDatePicker.native.js +1 -1
- package/dist/esm/fields/DatePicker/index.mjs +1 -1
- package/dist/esm/fields/DatePicker/index.native.js +1 -1
- package/dist/esm/fields/Progress/index.mjs +24 -2
- package/dist/esm/fields/Progress/index.mjs.map +1 -1
- package/dist/esm/fields/Progress/index.native.js +25 -2
- package/dist/esm/fields/Progress/index.native.js.map +1 -1
- package/dist/jsx/fields/DatePicker/Calendar.mjs +1 -1
- package/dist/jsx/fields/DatePicker/Calendar.native.js +1 -1
- package/dist/jsx/fields/DatePicker/DateRangePicker.mjs +1 -1
- package/dist/jsx/fields/DatePicker/DateRangePicker.native.js +1 -1
- package/dist/jsx/fields/DatePicker/DatetimePicker.mjs +1 -1
- package/dist/jsx/fields/DatePicker/DatetimePicker.native.js +1 -1
- package/dist/jsx/fields/DatePicker/MultiDatePicker.mjs +1 -1
- package/dist/jsx/fields/DatePicker/MultiDatePicker.native.js +1 -1
- package/dist/jsx/fields/DatePicker/index.mjs +1 -1
- package/dist/jsx/fields/DatePicker/index.native.js +1 -1
- package/dist/jsx/fields/Progress/index.mjs +24 -2
- package/dist/jsx/fields/Progress/index.mjs.map +1 -1
- package/dist/jsx/fields/Progress/index.native.js +24 -1
- package/dist/jsx/fields/Progress/index.native.js.map +1 -1
- package/package.json +7 -7
- package/src/Wheel/index.tsx +1 -1
- package/src/fields/DatePicker/DatetimePicker.tsx +26 -20
- package/src/fields/DatePicker/fieldValueSync.tsx +34 -0
- package/src/fields/DatePicker/index.tsx +26 -20
- package/src/fields/Progress/Progress.spec.tsx +118 -1
- package/src/fields/Progress/Progress.stories.tsx +22 -0
- package/src/fields/Progress/index.tsx +26 -22
- package/src/fields/RadioGroup/index.tsx +13 -5
- package/src/fields/Rating/index.tsx +10 -2
- package/src/fields/Slider/index.tsx +24 -2
- package/src/shared/colorRamps.ts +16 -1
- package/types/fields/Progress/index.d.ts +10 -1
- package/types/fields/Progress/index.d.ts.map +1 -1
- package/types/index.d.ts +1 -1
- package/types/index.d.ts.map +1 -1
- package/src/fields/Progress/scratch-debug.spec.tsx +0 -35
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import type { DeepKeys, DeepValue } from "@tanstack/form-core";
|
|
2
2
|
import { useAccentOnSurface, useResolvedKnobs } from "@multiplatform.one/theme";
|
|
3
3
|
import { type ComponentProps, useCallback, useEffect, useRef, useState } from "react";
|
|
4
|
+
import { DatePickerFieldValueSync } from "./fieldValueSync";
|
|
4
5
|
import { coerceToDate } from "./utils";
|
|
5
6
|
import { AnimatePresence, type Popover, View, useProps } from "tamagui";
|
|
6
7
|
|
|
@@ -473,26 +474,31 @@ export function DatePicker<
|
|
|
473
474
|
const resolvedError = getFieldError(field, errorProp);
|
|
474
475
|
|
|
475
476
|
return (
|
|
476
|
-
|
|
477
|
-
|
|
478
|
-
|
|
479
|
-
|
|
480
|
-
|
|
481
|
-
|
|
482
|
-
|
|
483
|
-
|
|
484
|
-
|
|
485
|
-
|
|
486
|
-
|
|
487
|
-
|
|
488
|
-
|
|
489
|
-
|
|
490
|
-
|
|
491
|
-
|
|
492
|
-
|
|
493
|
-
|
|
494
|
-
|
|
495
|
-
|
|
477
|
+
<>
|
|
478
|
+
{/* Form branch displays from `selectedDate` — keep it synced to
|
|
479
|
+
the live field value (late seeds / programmatic updates). */}
|
|
480
|
+
<DatePickerFieldValueSync value={field.state.value} onSync={setSelectedDate} />
|
|
481
|
+
<FieldLayout
|
|
482
|
+
id={id}
|
|
483
|
+
label={label}
|
|
484
|
+
labelProps={labelProps}
|
|
485
|
+
error={resolvedError}
|
|
486
|
+
helperText={helperText}
|
|
487
|
+
required={required}
|
|
488
|
+
size={size}
|
|
489
|
+
knobProps={knobProps}
|
|
490
|
+
// LC-40: see standalone branch — FieldLayout carries dimWhole.
|
|
491
|
+
disabled={disabled}
|
|
492
|
+
>
|
|
493
|
+
<InputParts size={size || knobProps.sizeToken}>
|
|
494
|
+
{renderPopover(
|
|
495
|
+
!!resolvedError,
|
|
496
|
+
mergeFieldHandler(field, "handleBlur", onBlur),
|
|
497
|
+
mergeFieldHandler(field, "handleChange"),
|
|
498
|
+
)}
|
|
499
|
+
</InputParts>
|
|
500
|
+
</FieldLayout>
|
|
501
|
+
</>
|
|
496
502
|
);
|
|
497
503
|
}}
|
|
498
504
|
</Field>
|
|
@@ -1,7 +1,56 @@
|
|
|
1
1
|
import { describe, expect, it } from "vitest";
|
|
2
|
+
import { render } from "@testing-library/react";
|
|
2
3
|
import { renderWithProviders } from "@multiplatform.one/test-utils";
|
|
4
|
+
import {
|
|
5
|
+
createThemesBuilder,
|
|
6
|
+
defaultAccentTheme,
|
|
7
|
+
defaultBaseTheme,
|
|
8
|
+
defaultBuilderOptions,
|
|
9
|
+
} from "@multiplatform.one/theme";
|
|
10
|
+
import { configWithoutAnimations } from "@tamagui/config";
|
|
11
|
+
import { animationsCSS } from "@tamagui/config/v5-css";
|
|
12
|
+
import type { ReactElement } from "react";
|
|
13
|
+
import { TamaguiProvider, createTamagui } from "tamagui";
|
|
3
14
|
import { Form } from "../../Form";
|
|
4
|
-
import { Progress } from "./index";
|
|
15
|
+
import { Progress, type ProgressIntent } from "./index";
|
|
16
|
+
|
|
17
|
+
// The stock @tamagui/config themes used by renderWithProviders have no
|
|
18
|
+
// error/warning/success/accent sub-themes and no accentBackground token, so
|
|
19
|
+
// intent ramp resolution is invisible there. Mount the house theme builder's
|
|
20
|
+
// generated themes (the same ones the app config uses) to assert the real
|
|
21
|
+
// resolved fill tokens.
|
|
22
|
+
const houseThemes = createThemesBuilder(
|
|
23
|
+
defaultBaseTheme,
|
|
24
|
+
defaultAccentTheme,
|
|
25
|
+
defaultBuilderOptions,
|
|
26
|
+
).themes() as Record<string, Record<string, string>>;
|
|
27
|
+
|
|
28
|
+
const houseConfig = createTamagui({
|
|
29
|
+
...configWithoutAnimations,
|
|
30
|
+
animations: animationsCSS,
|
|
31
|
+
themes: houseThemes as any,
|
|
32
|
+
});
|
|
33
|
+
|
|
34
|
+
function renderWithHouseThemes(ui: ReactElement) {
|
|
35
|
+
return render(
|
|
36
|
+
<TamaguiProvider config={houseConfig} defaultTheme="light" disableInjectCSS>
|
|
37
|
+
{ui}
|
|
38
|
+
</TamaguiProvider>,
|
|
39
|
+
);
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
function getIndicator(container: Element): Element | null {
|
|
43
|
+
return container.querySelector("[role='progressbar'] .is_ProgressIndicator");
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
/**
|
|
47
|
+
* First three numeric groups (h, s, l) of an hsla() string — the digit
|
|
48
|
+
* prefix Tamagui embeds in the atomic class it generates for a concrete
|
|
49
|
+
* color value (e.g. hsla(358, 75%, 59%, 1) → `_bg-hsla3587559<hash>`).
|
|
50
|
+
*/
|
|
51
|
+
function hslDigits(hsla: string): string {
|
|
52
|
+
return (hsla.match(/\d+/g) ?? []).slice(0, 3).join("");
|
|
53
|
+
}
|
|
5
54
|
|
|
6
55
|
describe("Progress", () => {
|
|
7
56
|
describe("without form context", () => {
|
|
@@ -48,4 +97,72 @@ describe("Progress", () => {
|
|
|
48
97
|
expect(result.findTextElement("Progress")).toBeDefined();
|
|
49
98
|
});
|
|
50
99
|
});
|
|
100
|
+
|
|
101
|
+
describe("intent", () => {
|
|
102
|
+
it("default keeps the gray form ramp: no intent theme scope, no intent fill token", () => {
|
|
103
|
+
const { container } = renderWithHouseThemes(<Progress label="Default" name="d" value={50} />);
|
|
104
|
+
const bar = container.querySelector("[role='progressbar']") as Element;
|
|
105
|
+
const indicator = getIndicator(container) as Element;
|
|
106
|
+
expect(indicator).toBeTruthy();
|
|
107
|
+
// No intent sub-theme scope anywhere inside the bar
|
|
108
|
+
for (const scope of [".t_accent", ".t_error", ".t_warning", ".t_success"]) {
|
|
109
|
+
expect(bar.querySelector(scope)).toBeNull();
|
|
110
|
+
}
|
|
111
|
+
// Fill stays on the ProgressIndicator component theme's gray form ramp
|
|
112
|
+
// (the pre-intent default) — not an intent token.
|
|
113
|
+
expect(indicator.className).toContain("_bg-background");
|
|
114
|
+
expect(indicator.className).not.toContain("_bg-color9");
|
|
115
|
+
expect(indicator.className).not.toContain("_bg-accentBackg");
|
|
116
|
+
});
|
|
117
|
+
|
|
118
|
+
it("accent fills from the base theme's $accentBackground without a sub-theme scope", () => {
|
|
119
|
+
const { container } = renderWithHouseThemes(
|
|
120
|
+
<Progress label="Accent" name="a" value={50} intent="accent" />,
|
|
121
|
+
);
|
|
122
|
+
const bar = container.querySelector("[role='progressbar']") as Element;
|
|
123
|
+
const indicator = getIndicator(container) as Element;
|
|
124
|
+
// Accent rides the base theme (the "accent" sub-theme is the SOLID
|
|
125
|
+
// ramp — wrong for a fill), so no t_accent scope is emitted.
|
|
126
|
+
expect(bar.querySelector(".t_accent")).toBeNull();
|
|
127
|
+
expect(indicator.className).toContain("_bg-accentBackg");
|
|
128
|
+
expect(indicator.className).not.toContain("_bg-color9");
|
|
129
|
+
});
|
|
130
|
+
|
|
131
|
+
it.each(["error", "warning", "success"] as ProgressIntent[])(
|
|
132
|
+
"%s rides its hue sub-theme: t_<intent> scope + the hue's $color9 solid fill",
|
|
133
|
+
(intent) => {
|
|
134
|
+
const { container } = renderWithHouseThemes(
|
|
135
|
+
<Progress label={intent} name={intent} value={50} intent={intent} />,
|
|
136
|
+
);
|
|
137
|
+
const bar = container.querySelector("[role='progressbar']") as Element;
|
|
138
|
+
const indicator = getIndicator(container) as Element;
|
|
139
|
+
// The Intent wrapper scopes the hue sub-theme around the indicator...
|
|
140
|
+
expect(bar.querySelector(`.t_${intent}`)).toBeTruthy();
|
|
141
|
+
// ...and the fill is the hue sub-theme's $color9 — captured as a
|
|
142
|
+
// concrete value from the Intent scope, so Tamagui's auto-applied
|
|
143
|
+
// ProgressIndicator COMPONENT theme (whose re-ramped color9 is a
|
|
144
|
+
// pale wash, not the solid) cannot re-resolve it.
|
|
145
|
+
const hueSolid = houseThemes[`light_${intent}`].color9;
|
|
146
|
+
expect(hueSolid).toBeTruthy();
|
|
147
|
+
expect(indicator.className).toContain(`_bg-hsla${hslDigits(hueSolid)}`);
|
|
148
|
+
expect(hueSolid).not.toBe(houseThemes[`light_${intent}_ProgressIndicator`]?.color9);
|
|
149
|
+
// LC-05 tint-independence: the hue solid is identical in both schemes.
|
|
150
|
+
expect(houseThemes[`dark_${intent}`].color9).toBe(hueSolid);
|
|
151
|
+
expect(indicator.className).not.toContain("_bg-accentBackg");
|
|
152
|
+
},
|
|
153
|
+
);
|
|
154
|
+
|
|
155
|
+
it("default render is unchanged under the standard test providers", () => {
|
|
156
|
+
const { container } = renderWithProviders(<Progress label="Plain" name="plain" value={40} />);
|
|
157
|
+
const bar = container.querySelector("[role='progressbar']") as Element;
|
|
158
|
+
const indicator = getIndicator(container) as Element;
|
|
159
|
+
expect(indicator).toBeTruthy();
|
|
160
|
+
// No intent scope and no Theme wrapper beyond Tamagui's own
|
|
161
|
+
// ProgressIndicator component-theme span.
|
|
162
|
+
for (const scope of [".t_accent", ".t_error", ".t_warning", ".t_success"]) {
|
|
163
|
+
expect(bar.querySelector(scope)).toBeNull();
|
|
164
|
+
}
|
|
165
|
+
expect(indicator.className).not.toContain("_bg-color9");
|
|
166
|
+
});
|
|
167
|
+
});
|
|
51
168
|
});
|
|
@@ -22,6 +22,11 @@ const meta: Meta<typeof Progress> = {
|
|
|
22
22
|
size: { control: "select", options: ["$2", "$3", "$4"], description: "Field size" },
|
|
23
23
|
value: { control: { type: "number", min: 0, max: 100 }, description: "Progress value" },
|
|
24
24
|
max: { control: "number", description: "Maximum value" },
|
|
25
|
+
intent: {
|
|
26
|
+
control: "select",
|
|
27
|
+
options: ["accent", "error", "warning", "success"],
|
|
28
|
+
description: "Semantic indicator fill resolved via the theme ramps",
|
|
29
|
+
},
|
|
25
30
|
},
|
|
26
31
|
};
|
|
27
32
|
|
|
@@ -106,6 +111,23 @@ export const Sizes: Story = {
|
|
|
106
111
|
),
|
|
107
112
|
};
|
|
108
113
|
|
|
114
|
+
/**
|
|
115
|
+
* Semantic indicator fills (LC-05): `accent` rides the base theme's
|
|
116
|
+
* `$accentBackground`; `error`/`warning`/`success` ride their hue
|
|
117
|
+
* sub-theme's `$color9`. Default keeps the gray form ramp.
|
|
118
|
+
*/
|
|
119
|
+
export const Intents: Story = {
|
|
120
|
+
render: () => (
|
|
121
|
+
<YStack gap="$4" maxWidth={400}>
|
|
122
|
+
<Progress label="Default (form ramp)" value={65} max={100} />
|
|
123
|
+
<Progress label="Accent" intent="accent" value={65} max={100} />
|
|
124
|
+
<Progress label="Error" intent="error" value={65} max={100} />
|
|
125
|
+
<Progress label="Warning" intent="warning" value={65} max={100} />
|
|
126
|
+
<Progress label="Success" intent="success" value={65} max={100} />
|
|
127
|
+
</YStack>
|
|
128
|
+
),
|
|
129
|
+
};
|
|
130
|
+
|
|
109
131
|
export const Interactive: Story = {
|
|
110
132
|
render: () => {
|
|
111
133
|
const InteractiveExample = () => {
|
|
@@ -8,6 +8,7 @@ import {
|
|
|
8
8
|
View,
|
|
9
9
|
XStack,
|
|
10
10
|
styled,
|
|
11
|
+
useTheme,
|
|
11
12
|
} from "tamagui";
|
|
12
13
|
import { Field, FieldLayout } from "../../fieldLayout";
|
|
13
14
|
import { Skeleton } from "../../Skeleton";
|
|
@@ -41,20 +42,19 @@ const ProgressIndicator = styled(TamaguiProgress.Indicator, {
|
|
|
41
42
|
export type ProgressIntent = "accent" | "error" | "warning" | "success";
|
|
42
43
|
|
|
43
44
|
/**
|
|
44
|
-
* Semantic
|
|
45
|
-
*
|
|
46
|
-
*
|
|
47
|
-
*
|
|
45
|
+
* Semantic hue fill: `$color9`, the hue's tint-independent solid step (LC-05,
|
|
46
|
+
* the Gantt-bar recipe), rendered INSIDE `<Intent name>` so it resolves on
|
|
47
|
+
* the hue sub-theme. Captured as a concrete value (Button focus-ring
|
|
48
|
+
* precedent) rather than passed as a token: a `$color9` token on the
|
|
49
|
+
* indicator itself would re-resolve inside Tamagui's auto-applied
|
|
50
|
+
* `ProgressIndicator` COMPONENT sub-theme, whose re-ramped `color9` is a
|
|
51
|
+
* pale wash — not the hue solid. useTheme() subscribes, so scheme changes
|
|
52
|
+
* stay live.
|
|
48
53
|
*/
|
|
49
|
-
function
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
}:
|
|
53
|
-
intent?: ProgressIntent;
|
|
54
|
-
children: ReactNode;
|
|
55
|
-
}) {
|
|
56
|
-
if (!intent || intent === "accent") return <>{children}</>;
|
|
57
|
-
return <Intent name={intent}>{children}</Intent>;
|
|
54
|
+
function HueFillIndicator() {
|
|
55
|
+
const theme = useTheme();
|
|
56
|
+
const fill = theme.color9?.val;
|
|
57
|
+
return <ProgressIndicator {...(fill ? { backgroundColor: fill as any } : undefined)} />;
|
|
58
58
|
}
|
|
59
59
|
|
|
60
60
|
export interface ProgressProps {
|
|
@@ -130,12 +130,6 @@ export function Progress({
|
|
|
130
130
|
blurHandler?: (...args: any[]) => void,
|
|
131
131
|
hasError?: boolean,
|
|
132
132
|
) => {
|
|
133
|
-
// undefined keeps the styled default (gray form ramp) for existing consumers.
|
|
134
|
-
const indicatorFill = intent
|
|
135
|
-
? intent === "accent"
|
|
136
|
-
? ("$accentBackground" as const)
|
|
137
|
-
: ("$color9" as const)
|
|
138
|
-
: undefined;
|
|
139
133
|
const progressElement = (
|
|
140
134
|
<ProgressFrame
|
|
141
135
|
width="100%"
|
|
@@ -152,9 +146,19 @@ export function Progress({
|
|
|
152
146
|
aria-required={required || undefined}
|
|
153
147
|
aria-invalid={hasError || undefined}
|
|
154
148
|
>
|
|
155
|
-
|
|
156
|
-
<
|
|
157
|
-
|
|
149
|
+
{intent && intent !== "accent" ? (
|
|
150
|
+
<Intent name={intent}>
|
|
151
|
+
<HueFillIndicator />
|
|
152
|
+
</Intent>
|
|
153
|
+
) : (
|
|
154
|
+
// `accent` rides the base theme's `$accentBackground` — the exact
|
|
155
|
+
// fill the bespoke XP bar used (the "accent" sub-theme is the SOLID
|
|
156
|
+
// ramp, wrong for a fill; same reasoning as Gantt bars / Toast).
|
|
157
|
+
// undefined keeps the styled default (gray form ramp) untouched.
|
|
158
|
+
<ProgressIndicator
|
|
159
|
+
backgroundColor={intent === "accent" ? "$accentBackground" : undefined}
|
|
160
|
+
/>
|
|
161
|
+
)}
|
|
158
162
|
</ProgressFrame>
|
|
159
163
|
);
|
|
160
164
|
|
|
@@ -16,7 +16,7 @@ import {
|
|
|
16
16
|
import { getSize } from "@tamagui/get-token";
|
|
17
17
|
import { Skeleton } from "../../Skeleton";
|
|
18
18
|
import { Field, FieldLayout } from "../../fieldLayout";
|
|
19
|
-
import { formControlColors } from "../../shared/colorRamps";
|
|
19
|
+
import { formControlColors, formSelectedColors } from "../../shared/colorRamps";
|
|
20
20
|
import {
|
|
21
21
|
getElevationWrapperProps,
|
|
22
22
|
getFieldError,
|
|
@@ -284,7 +284,10 @@ export function RadioGroup({
|
|
|
284
284
|
>
|
|
285
285
|
<RadioIndicatorFrame
|
|
286
286
|
borderRadius={indicatorRadius}
|
|
287
|
-
|
|
287
|
+
// LC-05: the dot is the selection mark, so it paints the active
|
|
288
|
+
// accent — `textAccentColor` is the LABEL ink tier ($color/$color11)
|
|
289
|
+
// and made the checked radio read as ink, not as chosen (D-01).
|
|
290
|
+
backgroundColor={formSelectedColors.mark}
|
|
288
291
|
{...(knobProps.transition ? { animation: knobProps.transition } : undefined)}
|
|
289
292
|
/>
|
|
290
293
|
</RadioGlyph>
|
|
@@ -472,9 +475,14 @@ export function RadioGroup({
|
|
|
472
475
|
handleChange?.(val);
|
|
473
476
|
handleValueChange(val);
|
|
474
477
|
};
|
|
475
|
-
//
|
|
476
|
-
//
|
|
477
|
-
|
|
478
|
+
// Always controlled: `radioValue` is the live upstream value (controlled
|
|
479
|
+
// `value` prop, TanStack field state, or the internal uncontrolled state,
|
|
480
|
+
// which `emit` keeps current) — passing it as Tamagui `defaultValue` was
|
|
481
|
+
// mount-only, so a value arriving AFTER first paint (e.g. create-mode
|
|
482
|
+
// engine seeding) never displayed. Tamagui's prop-wins controllable state
|
|
483
|
+
// adopts a late-arriving prop without firing onValueChange (LC-14: a
|
|
484
|
+
// programmatic value application is not a user edit).
|
|
485
|
+
const valueProps = { value: radioValue };
|
|
478
486
|
|
|
479
487
|
// WAI-ARIA radio group: arrow keys move focus AND select the newly
|
|
480
488
|
// focused radio (Tab entry alone never selects). Tamagui's roving group
|
|
@@ -8,6 +8,7 @@ import { getVariable, isWeb, styled, useTheme, View, XStack } from "tamagui";
|
|
|
8
8
|
import Svg, { Path } from "react-native-svg";
|
|
9
9
|
import { Skeleton } from "../../Skeleton";
|
|
10
10
|
import { Field, FieldLayout } from "../../fieldLayout";
|
|
11
|
+
import { formSelectedColors } from "../../shared/colorRamps";
|
|
11
12
|
import { t } from "../../shared/t";
|
|
12
13
|
import {
|
|
13
14
|
getFieldError,
|
|
@@ -304,9 +305,16 @@ export function Rating({
|
|
|
304
305
|
const resolvedValidators = useResolvedValidators(required, validators, label, name);
|
|
305
306
|
const filledStars = useMemo(() => Math.round(value * maxStars), [value, maxStars]);
|
|
306
307
|
|
|
307
|
-
// Resolve color tokens to actual CSS values for Phosphor icons
|
|
308
|
+
// Resolve color tokens to actual CSS values for Phosphor icons.
|
|
309
|
+
// LC-05: the FILLED star is the selection mark, so it resolves the shared
|
|
310
|
+
// accent mark token — it painted `$color10`, a muted neutral that made a
|
|
311
|
+
// 3-star rating read as disabled chrome rather than as a chosen value
|
|
312
|
+
// (D-01). The empty star stays neutral: it marks nothing.
|
|
308
313
|
const theme = useTheme();
|
|
309
|
-
const
|
|
314
|
+
const markToken = formSelectedColors.mark.slice(1);
|
|
315
|
+
const filledColor = getVariable(
|
|
316
|
+
(theme as any)[markToken]?.get("web") ?? theme.color10?.get("web") ?? theme.color?.get("web"),
|
|
317
|
+
);
|
|
310
318
|
const emptyColor = getVariable(theme.color7?.get("web") ?? theme.color?.get("web"));
|
|
311
319
|
|
|
312
320
|
const handleStarPress = (
|
|
@@ -125,6 +125,13 @@ export interface SliderProps {
|
|
|
125
125
|
type SliderControlProps = {
|
|
126
126
|
id: string;
|
|
127
127
|
sliderValue: number[];
|
|
128
|
+
/**
|
|
129
|
+
* True when `sliderValue` is a live upstream value (controlled `value` prop
|
|
130
|
+
* or TanStack field state): tamagui then runs controlled so a value arriving
|
|
131
|
+
* AFTER mount still moves the thumb. False keeps the mount-only
|
|
132
|
+
* `defaultValue` for genuinely uncontrolled standalone use.
|
|
133
|
+
*/
|
|
134
|
+
controlled?: boolean;
|
|
128
135
|
min: number;
|
|
129
136
|
max: number;
|
|
130
137
|
step: number;
|
|
@@ -156,6 +163,7 @@ type SliderControlProps = {
|
|
|
156
163
|
function SliderControl({
|
|
157
164
|
id,
|
|
158
165
|
sliderValue,
|
|
166
|
+
controlled,
|
|
159
167
|
min,
|
|
160
168
|
max,
|
|
161
169
|
step,
|
|
@@ -303,6 +311,9 @@ function SliderControl({
|
|
|
303
311
|
if (!isWeb) {
|
|
304
312
|
setNativeValues(sliderValue);
|
|
305
313
|
setA11yValues(null);
|
|
314
|
+
// Keep the FLIP replica's value mirror current so the next track-press
|
|
315
|
+
// glide computes its origin from the externally-applied position.
|
|
316
|
+
jumpMotion.onInternalValueChange(sliderValue);
|
|
306
317
|
}
|
|
307
318
|
if (sessionRef.current === "drag") return;
|
|
308
319
|
if (Date.now() < ignoreJumpUntilRef.current) return;
|
|
@@ -345,7 +356,12 @@ function SliderControl({
|
|
|
345
356
|
{...(disabled ? disabledState.chromeKnobProps : undefined)}
|
|
346
357
|
{...(readOnly ? { pointerEvents: "none" as const } : undefined)}
|
|
347
358
|
id={id}
|
|
348
|
-
|
|
359
|
+
// Controlled when an upstream value drives the slider (value prop /
|
|
360
|
+
// field state) — mount-only `defaultValue` froze late-arriving values
|
|
361
|
+
// (create-mode seeding). Uncontrolled standalone keeps defaultValue.
|
|
362
|
+
// Tamagui's prop-wins controllable state adopts a late prop without
|
|
363
|
+
// firing onValueChange (LC-14). Same split as ToggleGroup.
|
|
364
|
+
{...(controlled ? { value: sliderValue } : { defaultValue: sliderValue })}
|
|
349
365
|
// Native only: while VoiceOver adjusts the value the slider runs
|
|
350
366
|
// controlled (tamagui syncs its internal state to the prop), and the
|
|
351
367
|
// next touch gesture releases it back to uncontrolled seamlessly.
|
|
@@ -564,6 +580,7 @@ export function Slider({
|
|
|
564
580
|
|
|
565
581
|
const control = (
|
|
566
582
|
sliderValue: number[],
|
|
583
|
+
isControlled: boolean,
|
|
567
584
|
handleChange?: (values: number[]) => void,
|
|
568
585
|
handleBlur?: (...args: any[]) => void,
|
|
569
586
|
hasError?: boolean,
|
|
@@ -571,6 +588,7 @@ export function Slider({
|
|
|
571
588
|
<SliderControl
|
|
572
589
|
id={id}
|
|
573
590
|
sliderValue={sliderValue}
|
|
591
|
+
controlled={isControlled}
|
|
574
592
|
min={min}
|
|
575
593
|
max={max}
|
|
576
594
|
step={step}
|
|
@@ -610,7 +628,7 @@ export function Slider({
|
|
|
610
628
|
knobProps={knobProps}
|
|
611
629
|
disabled={disabled}
|
|
612
630
|
>
|
|
613
|
-
{control(value ?? defaultValue ?? [min], undefined, onBlur, !!error)}
|
|
631
|
+
{control(value ?? defaultValue ?? [min], value !== undefined, undefined, onBlur, !!error)}
|
|
614
632
|
</FieldLayout>
|
|
615
633
|
);
|
|
616
634
|
}
|
|
@@ -644,6 +662,10 @@ export function Slider({
|
|
|
644
662
|
>
|
|
645
663
|
{control(
|
|
646
664
|
value !== undefined ? value : normalizedValue,
|
|
665
|
+
// Form-integrated is always controlled: field state is the live
|
|
666
|
+
// source and handleChange below closes the loop (ToggleGroup
|
|
667
|
+
// form branch does the same).
|
|
668
|
+
true,
|
|
647
669
|
(values) => {
|
|
648
670
|
field.handleChange((values.length > 1 ? values : values[0]) as any);
|
|
649
671
|
},
|
package/src/shared/colorRamps.ts
CHANGED
|
@@ -51,13 +51,28 @@ export const formControlColors = {
|
|
|
51
51
|
},
|
|
52
52
|
} as const;
|
|
53
53
|
|
|
54
|
+
/**
|
|
55
|
+
* Selected/checked MARK channel (LC-05 ONE-EMPHASIS).
|
|
56
|
+
*
|
|
57
|
+
* Every choice control in the field family marks its selection with the ACTIVE
|
|
58
|
+
* ACCENT — the radio dot, the filled rating star and the checked Switch track
|
|
59
|
+
* all resolve here — so a user learns one meaning for the accent instead of
|
|
60
|
+
* decoding a per-control dialect. Ink marks selection nowhere (D-01).
|
|
61
|
+
* Marks are non-text chrome, so the floor they must clear is the 3:1
|
|
62
|
+
* graphical-object tier, not the 4.5:1 text tier; text placed ON this fill
|
|
63
|
+
* takes `useReadableTextOn` rather than an assumed anchor.
|
|
64
|
+
*/
|
|
65
|
+
export const formSelectedColors = {
|
|
66
|
+
mark: "$accentBackground",
|
|
67
|
+
} as const;
|
|
68
|
+
|
|
54
69
|
// Bento switch polarity: accent track when on, light thumb. Separate from
|
|
55
70
|
// formControlColors.thumb, which Slider still uses with inverted polarity.
|
|
56
71
|
// Checked state uses the accent solid so on/off reads at a glance and
|
|
57
72
|
// matches the accent CTAs on the same screen (SB-D-19).
|
|
58
73
|
export const formSwitchColors = {
|
|
59
74
|
track: {
|
|
60
|
-
on:
|
|
75
|
+
on: formSelectedColors.mark,
|
|
61
76
|
off: "$color5",
|
|
62
77
|
},
|
|
63
78
|
thumb: "$color1",
|
|
@@ -2,6 +2,8 @@ import type { ReactNode } from "react";
|
|
|
2
2
|
import type { AnyFormApi } from "../../types";
|
|
3
3
|
import type { LabelProps, SizeTokens } from "tamagui";
|
|
4
4
|
import { type ProgressProps as TamaguiProgressProps } from "tamagui";
|
|
5
|
+
/** Semantic indicator intent — matches the theme's Intent union. */
|
|
6
|
+
export type ProgressIntent = "accent" | "error" | "warning" | "success";
|
|
5
7
|
export interface ProgressProps {
|
|
6
8
|
name?: string;
|
|
7
9
|
form?: AnyFormApi;
|
|
@@ -19,10 +21,17 @@ export interface ProgressProps {
|
|
|
19
21
|
max?: number;
|
|
20
22
|
onBlur?: (...args: any[]) => void;
|
|
21
23
|
progressProps?: Omit<TamaguiProgressProps, "value" | "max" | "id" | "children">;
|
|
24
|
+
/**
|
|
25
|
+
* Semantic indicator fill resolved via the theme ramps (LC-05): `accent`
|
|
26
|
+
* fills with the base theme's `$accentBackground`; `error`/`warning`/
|
|
27
|
+
* `success` ride their hue sub-theme's `$color9`. Omit to keep the gray
|
|
28
|
+
* form ramp.
|
|
29
|
+
*/
|
|
30
|
+
intent?: ProgressIntent;
|
|
22
31
|
/** When true, renders a skeleton placeholder instead of the progress bar */
|
|
23
32
|
skeleton?: boolean;
|
|
24
33
|
/** When true, uses compact sizing */
|
|
25
34
|
compact?: boolean;
|
|
26
35
|
}
|
|
27
|
-
export declare function Progress({ name, form: formProp, validators, label, labelProps, helperText, error, required, size, id: idProp, value, defaultValue, max, onBlur, progressProps, skeleton, compact, }: ProgressProps): import("react/jsx-runtime").JSX.Element;
|
|
36
|
+
export declare function Progress({ name, form: formProp, validators, label, labelProps, helperText, error, required, size, id: idProp, value, defaultValue, max, onBlur, progressProps, intent, skeleton, compact, }: ProgressProps): import("react/jsx-runtime").JSX.Element;
|
|
28
37
|
//# sourceMappingURL=index.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/fields/Progress/index.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,OAAO,CAAC;AACvC,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,aAAa,CAAC;
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/fields/Progress/index.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,OAAO,CAAC;AACvC,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,aAAa,CAAC;AAE9C,OAAO,KAAK,EAAE,UAAU,EAAE,UAAU,EAAE,MAAM,SAAS,CAAC;AACtD,OAAO,EAEL,KAAK,aAAa,IAAI,oBAAoB,EAK3C,MAAM,SAAS,CAAC;AA6BjB,oEAAoE;AACpE,MAAM,MAAM,cAAc,GAAG,QAAQ,GAAG,OAAO,GAAG,SAAS,GAAG,SAAS,CAAC;AAkBxE,MAAM,WAAW,aAAa;IAC5B,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,IAAI,CAAC,EAAE,UAAU,CAAC;IAClB,UAAU,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;IACrC,KAAK,CAAC,EAAE,SAAS,CAAC;IAClB,UAAU,CAAC,EAAE,IAAI,CAAC,UAAU,EAAE,SAAS,GAAG,KAAK,CAAC,CAAC;IACjD,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,KAAK,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC;IACzB,QAAQ,CAAC,EAAE,OAAO,CAAC;IACnB,QAAQ,CAAC,EAAE,OAAO,CAAC;IACnB,IAAI,CAAC,EAAE,UAAU,CAAC;IAClB,EAAE,CAAC,EAAE,MAAM,CAAC;IACZ,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,GAAG,CAAC,EAAE,MAAM,CAAC;IACb,MAAM,CAAC,EAAE,CAAC,GAAG,IAAI,EAAE,GAAG,EAAE,KAAK,IAAI,CAAC;IAClC,aAAa,CAAC,EAAE,IAAI,CAAC,oBAAoB,EAAE,OAAO,GAAG,KAAK,GAAG,IAAI,GAAG,UAAU,CAAC,CAAC;IAChF;;;;;OAKG;IACH,MAAM,CAAC,EAAE,cAAc,CAAC;IACxB,4EAA4E;IAC5E,QAAQ,CAAC,EAAE,OAAO,CAAC;IACnB,qCAAqC;IACrC,OAAO,CAAC,EAAE,OAAO,CAAC;CACnB;AAED,wBAAgB,QAAQ,CAAC,EACvB,IAAI,EACJ,IAAI,EAAE,QAAQ,EACd,UAAU,EACV,KAAK,EACL,UAAU,EACV,UAAU,EACV,KAAK,EACL,QAAQ,EACR,IAAI,EACJ,EAAE,EAAE,MAAM,EACV,KAAK,EACL,YAAY,EACZ,GAAS,EACT,MAAM,EACN,aAAa,EACb,MAAM,EACN,QAAQ,EACR,OAAO,GACR,EAAE,aAAa,2CAwHf"}
|
package/types/index.d.ts
CHANGED
|
@@ -37,7 +37,7 @@ export { Label } from "./Label";
|
|
|
37
37
|
export { Spinner } from "./Spinner";
|
|
38
38
|
export type { SpinnerProps } from "./Spinner";
|
|
39
39
|
export { Progress } from "./fields/Progress";
|
|
40
|
-
export type { ProgressProps } from "./fields/Progress";
|
|
40
|
+
export type { ProgressIntent, ProgressProps } from "./fields/Progress";
|
|
41
41
|
export { DatePicker, MultiDatePicker, DateRangePicker, Calendar, MonthPicker, DatetimePicker, } from "./fields/DatePicker";
|
|
42
42
|
export type { DatePickerProps, DateRange, MultiDatePickerProps, DateRangePickerProps, CalendarProps, CalendarMode, MonthPickerProps, MonthPickerValue, DatetimePickerProps, } from "./fields/DatePicker";
|
|
43
43
|
export { OTPInput } from "./fields/OTPInput";
|
package/types/index.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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"}
|
|
@@ -1,35 +0,0 @@
|
|
|
1
|
-
import { writeFileSync } from "node:fs";
|
|
2
|
-
import { describe, it } from "vitest";
|
|
3
|
-
import { renderWithProviders } from "@multiplatform.one/test-utils";
|
|
4
|
-
import { View } from "tamagui";
|
|
5
|
-
|
|
6
|
-
describe("scratch", () => {
|
|
7
|
-
it("dumps config + view classes", () => {
|
|
8
|
-
const lines: string[] = [];
|
|
9
|
-
const { container } = renderWithProviders(
|
|
10
|
-
<>
|
|
11
|
-
<View data-testid="v-color7" backgroundColor="$color7" />
|
|
12
|
-
<View data-testid="v-accentbg" backgroundColor="$accentBackground" />
|
|
13
|
-
<View data-testid="v-color9" backgroundColor="$color9" />
|
|
14
|
-
</>,
|
|
15
|
-
);
|
|
16
|
-
for (const id of ["v-color7", "v-accentbg", "v-color9"]) {
|
|
17
|
-
const el = container.querySelector(`[data-testid='${id}']`) as HTMLElement;
|
|
18
|
-
lines.push(`${id}: class=${el?.className}`);
|
|
19
|
-
lines.push(`${id}: style=${el?.getAttribute("style")}`);
|
|
20
|
-
}
|
|
21
|
-
const { configWithoutAnimations } = require("@tamagui/config");
|
|
22
|
-
const themeNames = Object.keys(configWithoutAnimations.themes ?? {});
|
|
23
|
-
lines.push(`\nTHEME COUNT: ${themeNames.length}`);
|
|
24
|
-
lines.push(
|
|
25
|
-
`INTENT-ISH THEMES: ${themeNames.filter((n) => /error|warning|success|accent|red|green|yellow/.test(n)).join(", ")}`,
|
|
26
|
-
);
|
|
27
|
-
const light = (configWithoutAnimations.themes ?? {}).light ?? {};
|
|
28
|
-
lines.push(
|
|
29
|
-
`LIGHT KEYS (accent/color7/color9): ${Object.keys(light)
|
|
30
|
-
.filter((k) => /accent|color7|color9|^background$/.test(k))
|
|
31
|
-
.join(", ")}`,
|
|
32
|
-
);
|
|
33
|
-
writeFileSync("/tmp/progress-config-dump.txt", lines.join("\n"));
|
|
34
|
-
});
|
|
35
|
-
});
|