@multiplatform.one/forms 6.3.0 → 6.4.1
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/fields/DatePicker/Calendar.tsx +1 -1
- package/src/fields/DatePicker/DateRangePicker.tsx +1 -1
- package/src/fields/DatePicker/DatetimePicker.tsx +1 -1
- package/src/fields/DatePicker/MultiDatePicker.tsx +1 -1
- package/src/fields/DatePicker/index.tsx +69 -22
- package/src/fields/Progress/Progress.spec.tsx +118 -1
- package/src/fields/Progress/Progress.stories.tsx +22 -0
- package/src/fields/Progress/index.tsx +42 -1
- package/src/fields/RadioGroup/index.tsx +8 -3
- package/src/fields/Slider/index.tsx +24 -2
- package/src/index.ts +1 -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
|
@@ -1,6 +1,14 @@
|
|
|
1
1
|
import type { DeepKeys, DeepValue } from "@tanstack/form-core";
|
|
2
2
|
import { useAccentOnSurface, useResolvedKnobs } from "@multiplatform.one/theme";
|
|
3
|
-
import {
|
|
3
|
+
import {
|
|
4
|
+
type ComponentProps,
|
|
5
|
+
type Dispatch,
|
|
6
|
+
type SetStateAction,
|
|
7
|
+
useCallback,
|
|
8
|
+
useEffect,
|
|
9
|
+
useRef,
|
|
10
|
+
useState,
|
|
11
|
+
} from "react";
|
|
4
12
|
import { coerceToDate } from "./utils";
|
|
5
13
|
import { AnimatePresence, type Popover, View, useProps } from "tamagui";
|
|
6
14
|
|
|
@@ -143,7 +151,7 @@ function DayGrid({ calendarData, selectedDate, onSelectDate, minDate, maxDate }:
|
|
|
143
151
|
{isSelected ? (
|
|
144
152
|
<Button.Text
|
|
145
153
|
key="text-selected"
|
|
146
|
-
transition="
|
|
154
|
+
transition="quick"
|
|
147
155
|
enterStyle={{ opacity: 0, y: 20 }}
|
|
148
156
|
exitStyle={{ opacity: 0, y: 20 }}
|
|
149
157
|
opacity={1}
|
|
@@ -246,6 +254,40 @@ function CalendarBody({
|
|
|
246
254
|
);
|
|
247
255
|
}
|
|
248
256
|
|
|
257
|
+
// ---------------------------------------------------------------------------
|
|
258
|
+
// FieldValueSync — form-integrated display sync
|
|
259
|
+
// ---------------------------------------------------------------------------
|
|
260
|
+
|
|
261
|
+
/**
|
|
262
|
+
* Mirrors the TanStack field value into the picker's display state
|
|
263
|
+
* (`selectedDate`). Without it the form branch only ever showed the
|
|
264
|
+
* mount-time value, so a value applied AFTER first paint (create-mode
|
|
265
|
+
* engine seeding, form.setFieldValue, live server merge) never rendered.
|
|
266
|
+
* Display-only: never calls onChange/onValueChange (LC-14 — a programmatic
|
|
267
|
+
* value application is not a user edit). Rendered inside the Field render
|
|
268
|
+
* prop, which re-renders on field state changes (hooks cannot live in the
|
|
269
|
+
* render prop itself — same extraction as Stepper/PhoneInput renderers).
|
|
270
|
+
*/
|
|
271
|
+
function DatePickerFieldValueSync({
|
|
272
|
+
value,
|
|
273
|
+
onSync,
|
|
274
|
+
}: {
|
|
275
|
+
value: unknown;
|
|
276
|
+
onSync: Dispatch<SetStateAction<Date | null>>;
|
|
277
|
+
}) {
|
|
278
|
+
useEffect(() => {
|
|
279
|
+
const next = coerceToDate(value);
|
|
280
|
+
// Keep the previous Date identity when the instant is unchanged so the
|
|
281
|
+
// sync never churns downstream effects (close-on-select watches state).
|
|
282
|
+
onSync((prev) =>
|
|
283
|
+
prev === next || (prev !== null && next !== null && prev.getTime() === next.getTime())
|
|
284
|
+
? prev
|
|
285
|
+
: next,
|
|
286
|
+
);
|
|
287
|
+
}, [value, onSync]);
|
|
288
|
+
return null;
|
|
289
|
+
}
|
|
290
|
+
|
|
249
291
|
// ---------------------------------------------------------------------------
|
|
250
292
|
// DatePicker — main exported component
|
|
251
293
|
// ---------------------------------------------------------------------------
|
|
@@ -473,26 +515,31 @@ export function DatePicker<
|
|
|
473
515
|
const resolvedError = getFieldError(field, errorProp);
|
|
474
516
|
|
|
475
517
|
return (
|
|
476
|
-
|
|
477
|
-
|
|
478
|
-
|
|
479
|
-
|
|
480
|
-
|
|
481
|
-
|
|
482
|
-
|
|
483
|
-
|
|
484
|
-
|
|
485
|
-
|
|
486
|
-
|
|
487
|
-
|
|
488
|
-
|
|
489
|
-
|
|
490
|
-
|
|
491
|
-
|
|
492
|
-
|
|
493
|
-
|
|
494
|
-
|
|
495
|
-
|
|
518
|
+
<>
|
|
519
|
+
{/* Form branch displays from `selectedDate` — keep it synced to
|
|
520
|
+
the live field value (late seeds / programmatic updates). */}
|
|
521
|
+
<DatePickerFieldValueSync value={field.state.value} onSync={setSelectedDate} />
|
|
522
|
+
<FieldLayout
|
|
523
|
+
id={id}
|
|
524
|
+
label={label}
|
|
525
|
+
labelProps={labelProps}
|
|
526
|
+
error={resolvedError}
|
|
527
|
+
helperText={helperText}
|
|
528
|
+
required={required}
|
|
529
|
+
size={size}
|
|
530
|
+
knobProps={knobProps}
|
|
531
|
+
// LC-40: see standalone branch — FieldLayout carries dimWhole.
|
|
532
|
+
disabled={disabled}
|
|
533
|
+
>
|
|
534
|
+
<InputParts size={size || knobProps.sizeToken}>
|
|
535
|
+
{renderPopover(
|
|
536
|
+
!!resolvedError,
|
|
537
|
+
mergeFieldHandler(field, "handleBlur", onBlur),
|
|
538
|
+
mergeFieldHandler(field, "handleChange"),
|
|
539
|
+
)}
|
|
540
|
+
</InputParts>
|
|
541
|
+
</FieldLayout>
|
|
542
|
+
</>
|
|
496
543
|
);
|
|
497
544
|
}}
|
|
498
545
|
</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 = () => {
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import type { ReactNode } from "react";
|
|
2
2
|
import type { AnyFormApi } from "../../types";
|
|
3
|
+
import { Intent } from "@multiplatform.one/theme";
|
|
3
4
|
import type { LabelProps, SizeTokens } from "tamagui";
|
|
4
5
|
import {
|
|
5
6
|
Progress as TamaguiProgress,
|
|
@@ -7,6 +8,7 @@ import {
|
|
|
7
8
|
View,
|
|
8
9
|
XStack,
|
|
9
10
|
styled,
|
|
11
|
+
useTheme,
|
|
10
12
|
} from "tamagui";
|
|
11
13
|
import { Field, FieldLayout } from "../../fieldLayout";
|
|
12
14
|
import { Skeleton } from "../../Skeleton";
|
|
@@ -36,6 +38,25 @@ const ProgressIndicator = styled(TamaguiProgress.Indicator, {
|
|
|
36
38
|
backgroundColor: formControlColors.border,
|
|
37
39
|
});
|
|
38
40
|
|
|
41
|
+
/** Semantic indicator intent — matches the theme's Intent union. */
|
|
42
|
+
export type ProgressIntent = "accent" | "error" | "warning" | "success";
|
|
43
|
+
|
|
44
|
+
/**
|
|
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.
|
|
53
|
+
*/
|
|
54
|
+
function HueFillIndicator() {
|
|
55
|
+
const theme = useTheme();
|
|
56
|
+
const fill = theme.color9?.val;
|
|
57
|
+
return <ProgressIndicator {...(fill ? { backgroundColor: fill as any } : undefined)} />;
|
|
58
|
+
}
|
|
59
|
+
|
|
39
60
|
export interface ProgressProps {
|
|
40
61
|
name?: string;
|
|
41
62
|
form?: AnyFormApi;
|
|
@@ -53,6 +74,13 @@ export interface ProgressProps {
|
|
|
53
74
|
max?: number;
|
|
54
75
|
onBlur?: (...args: any[]) => void;
|
|
55
76
|
progressProps?: Omit<TamaguiProgressProps, "value" | "max" | "id" | "children">;
|
|
77
|
+
/**
|
|
78
|
+
* Semantic indicator fill resolved via the theme ramps (LC-05): `accent`
|
|
79
|
+
* fills with the base theme's `$accentBackground`; `error`/`warning`/
|
|
80
|
+
* `success` ride their hue sub-theme's `$color9`. Omit to keep the gray
|
|
81
|
+
* form ramp.
|
|
82
|
+
*/
|
|
83
|
+
intent?: ProgressIntent;
|
|
56
84
|
/** When true, renders a skeleton placeholder instead of the progress bar */
|
|
57
85
|
skeleton?: boolean;
|
|
58
86
|
/** When true, uses compact sizing */
|
|
@@ -75,6 +103,7 @@ export function Progress({
|
|
|
75
103
|
max = 100,
|
|
76
104
|
onBlur,
|
|
77
105
|
progressProps,
|
|
106
|
+
intent,
|
|
78
107
|
skeleton,
|
|
79
108
|
compact,
|
|
80
109
|
}: ProgressProps) {
|
|
@@ -117,7 +146,19 @@ export function Progress({
|
|
|
117
146
|
aria-required={required || undefined}
|
|
118
147
|
aria-invalid={hasError || undefined}
|
|
119
148
|
>
|
|
120
|
-
|
|
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
|
+
)}
|
|
121
162
|
</ProgressFrame>
|
|
122
163
|
);
|
|
123
164
|
|
|
@@ -472,9 +472,14 @@ export function RadioGroup({
|
|
|
472
472
|
handleChange?.(val);
|
|
473
473
|
handleValueChange(val);
|
|
474
474
|
};
|
|
475
|
-
//
|
|
476
|
-
//
|
|
477
|
-
|
|
475
|
+
// Always controlled: `radioValue` is the live upstream value (controlled
|
|
476
|
+
// `value` prop, TanStack field state, or the internal uncontrolled state,
|
|
477
|
+
// which `emit` keeps current) — passing it as Tamagui `defaultValue` was
|
|
478
|
+
// mount-only, so a value arriving AFTER first paint (e.g. create-mode
|
|
479
|
+
// engine seeding) never displayed. Tamagui's prop-wins controllable state
|
|
480
|
+
// adopts a late-arriving prop without firing onValueChange (LC-14: a
|
|
481
|
+
// programmatic value application is not a user edit).
|
|
482
|
+
const valueProps = { value: radioValue };
|
|
478
483
|
|
|
479
484
|
// WAI-ARIA radio group: arrow keys move focus AND select the newly
|
|
480
485
|
// focused radio (Tab entry alone never selects). Tamagui's roving group
|
|
@@ -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/index.ts
CHANGED
|
@@ -124,7 +124,7 @@ export { Spinner } from "./Spinner";
|
|
|
124
124
|
export type { SpinnerProps } from "./Spinner";
|
|
125
125
|
|
|
126
126
|
export { Progress } from "./fields/Progress";
|
|
127
|
-
export type { ProgressProps } from "./fields/Progress";
|
|
127
|
+
export type { ProgressIntent, ProgressProps } from "./fields/Progress";
|
|
128
128
|
|
|
129
129
|
// ── Compound Components ──────────────────────────────────────
|
|
130
130
|
export {
|
|
@@ -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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"}
|