@kanso-labs/kanso-ui 0.20.0 → 0.22.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/dist/calendar/index.js +80 -0
- package/dist/calendar/index.js.map +1 -0
- package/dist/calendar/months.js +14 -0
- package/dist/calendar/months.js.map +1 -0
- package/dist/calendar/styles.js +150 -0
- package/dist/calendar/styles.js.map +1 -0
- package/dist/components/calendar/index.d.ts +32 -0
- package/dist/components/calendar/index.js +97 -0
- package/dist/components/calendar/index.js.map +1 -0
- package/dist/components/color-area/index.d.ts +50 -0
- package/dist/components/color-area/index.js +63 -0
- package/dist/components/color-area/index.js.map +1 -0
- package/dist/components/color-slider/index.d.ts +41 -0
- package/dist/components/color-slider/index.js +70 -0
- package/dist/components/color-slider/index.js.map +1 -0
- package/dist/components/color-swatch/index.d.ts +37 -0
- package/dist/components/color-swatch/index.js +88 -0
- package/dist/components/color-swatch/index.js.map +1 -0
- package/dist/components/color-swatch-picker/index.d.ts +49 -0
- package/dist/components/color-swatch-picker/index.js +99 -0
- package/dist/components/color-swatch-picker/index.js.map +1 -0
- package/dist/components/date-field/index.d.ts +54 -0
- package/dist/components/date-field/index.js +58 -0
- package/dist/components/date-field/index.js.map +1 -0
- package/dist/components/date-picker/index.d.ts +57 -0
- package/dist/components/date-picker/index.js +75 -0
- package/dist/components/date-picker/index.js.map +1 -0
- package/dist/components/date-range-picker/index.d.ts +69 -0
- package/dist/components/date-range-picker/index.js +95 -0
- package/dist/components/date-range-picker/index.js.map +1 -0
- package/dist/components/disclosure/index.js +3 -3
- package/dist/components/disclosure/index.js.map +1 -1
- package/dist/components/drop-zone/index.d.ts +60 -0
- package/dist/components/drop-zone/index.js +118 -0
- package/dist/components/drop-zone/index.js.map +1 -0
- package/dist/components/drop-zone/styles.js +61 -0
- package/dist/components/drop-zone/styles.js.map +1 -0
- package/dist/components/icon-button/index.d.ts +4 -3
- package/dist/components/icon-button/index.js +48 -2
- package/dist/components/icon-button/index.js.map +1 -1
- package/dist/components/index.d.ts +15 -1
- package/dist/components/list/index.js +3 -3
- package/dist/components/list/index.js.map +1 -1
- package/dist/components/list-box/index.js +3 -3
- package/dist/components/list-box/index.js.map +1 -1
- package/dist/components/list-item/index.d.ts +16 -6
- package/dist/components/list-item/index.js +16 -8
- package/dist/components/list-item/index.js.map +1 -1
- package/dist/components/navigation-tree/index.d.ts +94 -0
- package/dist/components/navigation-tree/index.js +266 -0
- package/dist/components/navigation-tree/index.js.map +1 -0
- package/dist/components/range-calendar/index.d.ts +39 -0
- package/dist/components/range-calendar/index.js +105 -0
- package/dist/components/range-calendar/index.js.map +1 -0
- package/dist/components/separator/index.d.ts +17 -4
- package/dist/components/separator/index.js +38 -20
- package/dist/components/separator/index.js.map +1 -1
- package/dist/components/table/index.d.ts +197 -0
- package/dist/components/table/index.js +327 -0
- package/dist/components/table/index.js.map +1 -0
- package/dist/components/time-field/index.d.ts +53 -0
- package/dist/components/time-field/index.js +57 -0
- package/dist/components/time-field/index.js.map +1 -0
- package/dist/components/tree/index.d.ts +116 -0
- package/dist/components/tree/index.js +245 -0
- package/dist/components/tree/index.js.map +1 -0
- package/dist/date.d.ts +1 -0
- package/dist/date.js +1 -0
- package/dist/drag/hooks.d.ts +25 -0
- package/dist/drag/hooks.js +55 -0
- package/dist/drag/hooks.js.map +1 -0
- package/dist/drag/index.js +28 -0
- package/dist/drag/index.js.map +1 -0
- package/dist/drag/styles.js +46 -0
- package/dist/drag/styles.js.map +1 -0
- package/dist/glyphs/index.js +64 -1
- package/dist/glyphs/index.js.map +1 -1
- package/dist/index.d.ts +18 -2
- package/dist/index.js +18 -2
- package/dist/layout.d.ts +40 -0
- package/dist/layout.js +41 -0
- package/dist/layout.js.map +1 -0
- package/dist/react-aria.d.ts +3 -2
- package/dist/react-aria.js +3 -2
- package/dist/row/index.js +25 -13
- package/dist/row/index.js.map +1 -1
- package/dist/row/styles.js +34 -0
- package/dist/row/styles.js.map +1 -1
- package/dist/segments/index.js +22 -0
- package/dist/segments/index.js.map +1 -0
- package/dist/segments/styles.js +42 -0
- package/dist/segments/styles.js.map +1 -0
- package/dist/styles/chequer.js +14 -0
- package/dist/styles/chequer.js.map +1 -0
- package/dist/styles/color.js +17 -0
- package/dist/styles/color.js.map +1 -0
- package/dist/styles/picker.js +61 -0
- package/dist/styles/picker.js.map +1 -0
- package/dist/styles.css +263 -3
- package/dist/tokens/design.tokens.stylex.js +61 -1
- package/dist/tokens/design.tokens.stylex.js.map +1 -1
- package/package.json +7 -2
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","names":[],"sources":["../../../src/components/date-picker/index.tsx"],"sourcesContent":["import type { ReactNode } from 'react';\nimport type { DateValue, DatePickerProps as RACDatePickerProps } from 'react-aria-components';\nimport * as stylex from '@stylexjs/stylex';\nimport { Button as RACButton, DateInput as RACDateInput, DatePicker as RACDatePicker, Dialog as RACDialog, Group as RACGroup, Popover as RACPopover } from 'react-aria-components';\nimport { FieldBox, FieldMessage, FieldValue } from '../../field';\nimport { fieldStyles, invalidFrom, useFieldValidationBehavior } from '../../field/root';\nimport { CalendarGlyph } from '../../glyphs';\nimport { renderSegment } from '../../segments';\nimport { segmentStyles } from '../../segments/styles';\nimport { mergeStatefulStyles } from '../../styles/merge';\nimport { overlay } from '../../styles/overlay';\nimport { picker, triggerClassName } from '../../styles/picker';\nimport Calendar from '../calendar';\n\n// The date pickers page's picker: the date field a date is typed into, with\n// a calendar behind a button for picking it instead. Both halves already\n// exist — the segments are `DateField`'s, from `src/segments`, and the\n// calendar is `Calendar` — so what this adds is the button between them and\n// the surface the calendar opens on.\n//\n// Two things are this component's own.\n//\n// **The picker is one field, not a field beside a button.** React Aria's\n// `Group` is what holds the segments and the trigger together, so the box\n// draws once around both and a reader tabs through the segments and reaches\n// the button at the end of them rather than as a separate control.\n//\n// **It is docked above the medium breakpoint and modal below it**, which is\n// the pairing the page draws and the same swap `Sheet` makes. It is done in\n// CSS rather than by rendering a different tree: a 360dp calendar anchored\n// to a field is unreachable at 375px, and a modal that stayed centred on a\n// desktop would cover a form for no reason. `Sheet` settles this the same\n// way, and doing it twice in two different ways is how the two would drift.\n\ntype DatePickerProps<T extends DateValue> = Omit<RACDatePickerProps<T>, 'children' | 'className' | 'style'> & {\n /** A function may compute the class from the picker's render state. */\n className?: RACDatePickerProps<T>['className'];\n /** Supporting text under the field. */\n description?: string;\n /** The message shown instead of the description, which also marks the field invalid. */\n error?: string;\n /**\n * Whether the label floats into the box's top once the field holds a\n * value, rather than sitting above it.\n * @default true\n */\n floatingLabel?: boolean;\n /** What the field is for. Always rendered; never a placeholder. */\n label: string;\n /** An icon at the box's leading end. */\n leadingIcon?: ReactNode;\n /** A function may compute the style from the picker's render state. */\n style?: RACDatePickerProps<T>['style'];\n /**\n * What the button that opens the calendar is called, for a screen reader.\n * @default 'Choose a date'\n */\n triggerLabel?: string;\n /**\n * Which of the text fields page's two boxes to draw.\n * @default 'filled'\n */\n variant?: 'filled' | 'outlined';\n};\n\n/**\n * A date typed into a field, or picked from a calendar behind a button. The\n * value is React Aria's — pass `value` with `onChange` to control it, or\n * `defaultValue` — as an `@internationalized/date` value from this package's\n * `./date` subpath.\n *\n * ```tsx\n * import { CalendarDate } from '@kanso-labs/kanso-ui/date'\n *\n * <DatePicker defaultValue={new CalendarDate(2026, 9, 15)} label=\"Label\" />\n * ```\n *\n * The segments are `DateField`'s and the calendar is `Calendar`, so\n * `granularity`, `minValue`, `maxValue` and `isDateUnavailable` all behave\n * as they do there. Above the medium breakpoint the calendar is docked to\n * the field; below it, it opens centred, which is the page's modal picker.\n *\n * The call site's `className` and `style` land on the picker as a whole,\n * which is the element a layout positions.\n */\nfunction DatePicker<T extends DateValue>({\n description,\n error,\n floatingLabel = true,\n isDisabled = false,\n label,\n leadingIcon,\n triggerLabel = 'Choose a date',\n variant = 'filled',\n ...props\n}: DatePickerProps<T>) {\n const validationBehavior = useFieldValidationBehavior();\n return <RACDatePicker<T> isDisabled={isDisabled} isInvalid={invalidFrom(error)} validationBehavior={validationBehavior} {...props} {...mergeStatefulStyles(stylex.props(fieldStyles.root), props)}>\n <FieldBox floatingLabel={floatingLabel}\n // Always populated, which buys exactly one thing: the outlined\n // notch. The box decides populated twice over — in CSS for the\n // label's type, and in React for the notch, since CSS cannot cut an\n // outline to a width it has no way to measure. React Aria renders a\n // hidden `<input type=\"date\">` carrying no placeholder, so the CSS\n // half reads as populated on its own; the React half reads React\n // Aria's input context, which a picker does not provide. Without\n // this the notch stays shut across segments already showing\n // `mm/dd/yyyy`.\n isPopulated label={label} leading={leadingIcon} variant={variant}>\n <FieldValue>\n <RACGroup {...stylex.props(picker.group)}>\n <RACDateInput {...stylex.props(segmentStyles.input)}>\n {renderSegment}\n </RACDateInput>\n <RACButton aria-label={triggerLabel} className={triggerClassName}>\n <CalendarGlyph {...stylex.props(picker.triggerGlyph)} />\n </RACButton>\n </RACGroup>\n </FieldValue>\n </FieldBox>\n <FieldMessage description={description} error={error} />\n <RACPopover {...stylex.props(overlay.popup, picker.popover)}>\n <RACDialog>\n <Calendar aria-label={label} />\n </RACDialog>\n </RACPopover>\n </RACDatePicker>;\n}\nexport type { DatePickerProps };\nexport default DatePicker;"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAqFA,SAAS,aAAgC,EACvC,aACA,OACA,gBAAgB,MAChB,aAAa,OACb,OACA,aACA,eAAe,iBACf,UAAU,UACV,GAAG,WACkB;CACrB,MAAM,qBAAqB,2BAA2B;CACtD,OAAO,qBAAC,YAAD;EAA8B;EAAY,WAAW,YAAY,KAAK;EAAuB;EAAoB,GAAI;EAAO,GAAI,oBAAoB,MAAa,YAAY,IAAI,GAAG,OAAK;EAAzL,UAAA;GACH,oBAAC,UAAD;IAAyB;IAU3B,aAAA;IAAmB;IAAO,SAAS;IAAsB;IACrD,UAAA,oBAAC,YAAD,EAAA,UACE,qBAAC,OAAD;KAAU,GAAI,MAAa,OAAO,KAAK;KAAvC,UAAA,CACE,oBAAC,WAAD;MAAc,GAAI,MAAa,cAAc,KAAK;MAC/C,UAAA;KACW,CAAA,GACd,oBAAC,QAAD;MAAW,cAAY;MAAc,WAAW;MAC9C,UAAA,oBAAC,eAAD,EAAe,GAAI,MAAa,OAAO,YAAY,EAAE,CAAA;KAC5C,CAAA,CACH;IACA,CAAA,EAAA,CAAA;GACJ,CAAA;GACV,oBAAC,cAAD;IAA2B;IAAoB;GAAM,CAAA;GACrD,oBAAC,SAAD;IAAY,GAAI,MAAa,QAAQ,OAAO,OAAO,OAAO;IACxD,UAAA,oBAAC,QAAD,EAAA,UACE,oBAAC,YAAD,EAAU,cAAY,MAAM,CAAA,EACnB,CAAA;GACD,CAAA;EACC;;AACnB"}
|
|
@@ -0,0 +1,69 @@
|
|
|
1
|
+
import { ReactNode } from "react";
|
|
2
|
+
import { DateRangePickerProps, DateValue } from "react-aria-components";
|
|
3
|
+
//#region src/components/date-range-picker/index.d.ts
|
|
4
|
+
type DateRangePickerProps$1<T extends DateValue> = {
|
|
5
|
+
/** A function may compute the class from the picker's render state. */
|
|
6
|
+
className?: DateRangePickerProps<T>['className'];
|
|
7
|
+
/** Supporting text under the field. */
|
|
8
|
+
description?: string;
|
|
9
|
+
/** The message shown instead of the description, which also marks the field invalid. */
|
|
10
|
+
error?: string;
|
|
11
|
+
/**
|
|
12
|
+
* Whether the label floats into the box's top once the field holds a
|
|
13
|
+
* value, rather than sitting above it.
|
|
14
|
+
* @default true
|
|
15
|
+
*/
|
|
16
|
+
floatingLabel?: boolean;
|
|
17
|
+
/** What the field is for. Always rendered; never a placeholder. */
|
|
18
|
+
label: string;
|
|
19
|
+
/** An icon at the box's leading end. */
|
|
20
|
+
leadingIcon?: ReactNode;
|
|
21
|
+
/**
|
|
22
|
+
* What is drawn between the two segment groups. Decoration — a screen
|
|
23
|
+
* reader is told which group is which by React Aria.
|
|
24
|
+
* @default '–'
|
|
25
|
+
*/
|
|
26
|
+
separator?: string;
|
|
27
|
+
/** A function may compute the style from the picker's render state. */
|
|
28
|
+
style?: DateRangePickerProps<T>['style'];
|
|
29
|
+
/**
|
|
30
|
+
* What the button that opens the calendar is called, for a screen reader.
|
|
31
|
+
* @default 'Choose a date range'
|
|
32
|
+
*/
|
|
33
|
+
triggerLabel?: string;
|
|
34
|
+
/**
|
|
35
|
+
* Which of the text fields page's two boxes to draw.
|
|
36
|
+
* @default 'filled'
|
|
37
|
+
*/
|
|
38
|
+
variant?: 'filled' | 'outlined';
|
|
39
|
+
} & Omit<DateRangePickerProps<T>, 'children' | 'className' | 'style'>;
|
|
40
|
+
/**
|
|
41
|
+
* A date range typed into a field, or picked from a calendar behind a
|
|
42
|
+
* button. The value is React Aria's — pass `value` with `onChange` to
|
|
43
|
+
* control it, or `defaultValue` — as a `{ start, end }` pair of
|
|
44
|
+
* `@internationalized/date` values from this package's `./date` subpath.
|
|
45
|
+
*
|
|
46
|
+
* ```tsx
|
|
47
|
+
* import { CalendarDate } from '@kanso-labs/kanso-ui/date'
|
|
48
|
+
*
|
|
49
|
+
* <DateRangePicker
|
|
50
|
+
* defaultValue={{
|
|
51
|
+
* end: new CalendarDate(2026, 9, 20),
|
|
52
|
+
* start: new CalendarDate(2026, 9, 15),
|
|
53
|
+
* }}
|
|
54
|
+
* label="Label"
|
|
55
|
+
* />
|
|
56
|
+
* ```
|
|
57
|
+
*
|
|
58
|
+
* The segments are `DateField`'s and the calendar is `RangeCalendar`, so
|
|
59
|
+
* `granularity`, `minValue`, `maxValue` and `isDateUnavailable` all behave
|
|
60
|
+
* as they do there. Above the medium breakpoint the calendar is docked to
|
|
61
|
+
* the field; below it, it opens centred, the same swap `DatePicker` makes.
|
|
62
|
+
*
|
|
63
|
+
* The call site's `className` and `style` land on the picker as a whole,
|
|
64
|
+
* which is the element a layout positions.
|
|
65
|
+
*/
|
|
66
|
+
declare function DateRangePicker$1<T extends DateValue>({ description, error, floatingLabel, isDisabled, label, leadingIcon, separator, triggerLabel, variant, ...props }: DateRangePickerProps$1<T>): import("react").JSX.Element;
|
|
67
|
+
//#endregion
|
|
68
|
+
export { type DateRangePickerProps$1 as DateRangePickerProps, DateRangePicker$1 as default };
|
|
69
|
+
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +1,95 @@
|
|
|
1
|
+
import { props } from "../../node_modules/@stylexjs/stylex/lib/es/stylex.js";
|
|
2
|
+
import { mergeStatefulStyles } from "../../styles/merge.js";
|
|
3
|
+
import { CalendarGlyph } from "../../glyphs/index.js";
|
|
4
|
+
import { fieldStyles, invalidFrom, useFieldValidationBehavior } from "../../field/root.js";
|
|
5
|
+
import { FieldBox, FieldMessage, FieldValue } from "../../field/index.js";
|
|
6
|
+
import { overlay } from "../../styles/overlay.js";
|
|
7
|
+
import { segmentStyles } from "../../segments/styles.js";
|
|
8
|
+
import { renderSegment } from "../../segments/index.js";
|
|
9
|
+
import { picker, triggerClassName } from "../../styles/picker.js";
|
|
10
|
+
import RangeCalendar$1 from "../range-calendar/index.js";
|
|
11
|
+
import { jsx, jsxs } from "react/jsx-runtime";
|
|
12
|
+
import { Button, DateInput, DateRangePicker, Dialog, Group, Popover } from "react-aria-components";
|
|
13
|
+
//#region src/components/date-range-picker/index.tsx
|
|
14
|
+
/**
|
|
15
|
+
* A date range typed into a field, or picked from a calendar behind a
|
|
16
|
+
* button. The value is React Aria's — pass `value` with `onChange` to
|
|
17
|
+
* control it, or `defaultValue` — as a `{ start, end }` pair of
|
|
18
|
+
* `@internationalized/date` values from this package's `./date` subpath.
|
|
19
|
+
*
|
|
20
|
+
* ```tsx
|
|
21
|
+
* import { CalendarDate } from '@kanso-labs/kanso-ui/date'
|
|
22
|
+
*
|
|
23
|
+
* <DateRangePicker
|
|
24
|
+
* defaultValue={{
|
|
25
|
+
* end: new CalendarDate(2026, 9, 20),
|
|
26
|
+
* start: new CalendarDate(2026, 9, 15),
|
|
27
|
+
* }}
|
|
28
|
+
* label="Label"
|
|
29
|
+
* />
|
|
30
|
+
* ```
|
|
31
|
+
*
|
|
32
|
+
* The segments are `DateField`'s and the calendar is `RangeCalendar`, so
|
|
33
|
+
* `granularity`, `minValue`, `maxValue` and `isDateUnavailable` all behave
|
|
34
|
+
* as they do there. Above the medium breakpoint the calendar is docked to
|
|
35
|
+
* the field; below it, it opens centred, the same swap `DatePicker` makes.
|
|
36
|
+
*
|
|
37
|
+
* The call site's `className` and `style` land on the picker as a whole,
|
|
38
|
+
* which is the element a layout positions.
|
|
39
|
+
*/
|
|
40
|
+
function DateRangePicker$1({ description, error, floatingLabel = true, isDisabled = false, label, leadingIcon, separator = "–", triggerLabel = "Choose a date range", variant = "filled", ...props$1 }) {
|
|
41
|
+
const validationBehavior = useFieldValidationBehavior();
|
|
42
|
+
return /* @__PURE__ */ jsxs(DateRangePicker, {
|
|
43
|
+
isDisabled,
|
|
44
|
+
isInvalid: invalidFrom(error),
|
|
45
|
+
validationBehavior,
|
|
46
|
+
...props$1,
|
|
47
|
+
...mergeStatefulStyles(props(fieldStyles.root), props$1),
|
|
48
|
+
children: [
|
|
49
|
+
/* @__PURE__ */ jsx(FieldBox, {
|
|
50
|
+
floatingLabel,
|
|
51
|
+
isPopulated: true,
|
|
52
|
+
label,
|
|
53
|
+
leading: leadingIcon,
|
|
54
|
+
variant,
|
|
55
|
+
children: /* @__PURE__ */ jsx(FieldValue, { children: /* @__PURE__ */ jsxs(Group, {
|
|
56
|
+
...props(picker.group),
|
|
57
|
+
children: [
|
|
58
|
+
/* @__PURE__ */ jsx(DateInput, {
|
|
59
|
+
slot: "start",
|
|
60
|
+
...props(segmentStyles.input),
|
|
61
|
+
children: renderSegment
|
|
62
|
+
}),
|
|
63
|
+
/* @__PURE__ */ jsx("span", {
|
|
64
|
+
"aria-hidden": "true",
|
|
65
|
+
className: "x1w5n3ug x2lah0s x16svsjw x1848etk xh7dzej",
|
|
66
|
+
children: separator
|
|
67
|
+
}),
|
|
68
|
+
/* @__PURE__ */ jsx(DateInput, {
|
|
69
|
+
slot: "end",
|
|
70
|
+
...props(segmentStyles.input),
|
|
71
|
+
children: renderSegment
|
|
72
|
+
}),
|
|
73
|
+
/* @__PURE__ */ jsx(Button, {
|
|
74
|
+
"aria-label": triggerLabel,
|
|
75
|
+
className: triggerClassName,
|
|
76
|
+
children: /* @__PURE__ */ jsx(CalendarGlyph, { ...props(picker.triggerGlyph) })
|
|
77
|
+
})
|
|
78
|
+
]
|
|
79
|
+
}) })
|
|
80
|
+
}),
|
|
81
|
+
/* @__PURE__ */ jsx(FieldMessage, {
|
|
82
|
+
description,
|
|
83
|
+
error
|
|
84
|
+
}),
|
|
85
|
+
/* @__PURE__ */ jsx(Popover, {
|
|
86
|
+
...props(overlay.popup, picker.popover),
|
|
87
|
+
children: /* @__PURE__ */ jsx(Dialog, { children: /* @__PURE__ */ jsx(RangeCalendar$1, { "aria-label": label }) })
|
|
88
|
+
})
|
|
89
|
+
]
|
|
90
|
+
});
|
|
91
|
+
}
|
|
92
|
+
//#endregion
|
|
93
|
+
export { DateRangePicker$1 as default };
|
|
94
|
+
|
|
95
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","names":[],"sources":["../../../src/components/date-range-picker/index.tsx"],"sourcesContent":["import type { ReactNode } from 'react';\nimport type { DateValue, DateRangePickerProps as RACDateRangePickerProps } from 'react-aria-components';\nimport * as stylex from '@stylexjs/stylex';\nimport { Button as RACButton, DateInput as RACDateInput, DateRangePicker as RACDateRangePicker, Dialog as RACDialog, Group as RACGroup, Popover as RACPopover } from 'react-aria-components';\nimport { FieldBox, FieldMessage, FieldValue } from '../../field';\nimport { fieldStyles, invalidFrom, useFieldValidationBehavior } from '../../field/root';\nimport { CalendarGlyph } from '../../glyphs';\nimport { renderSegment } from '../../segments';\nimport { segmentStyles } from '../../segments/styles';\nimport { mergeStatefulStyles } from '../../styles/merge';\nimport { overlay } from '../../styles/overlay';\nimport { picker, triggerClassName } from '../../styles/picker';\nimport '../../tokens/design.tokens.stylex';\nimport { colors, typography } from '../../tokens/design.tokens.stylex';\nimport RangeCalendar from '../range-calendar';\n\n// `DatePicker` picking two dates rather than one. Every part it draws is\n// already here — the segments from `src/segments`, the trigger and the\n// overlay from `src/styles/picker`, the calendar from `RangeCalendar` — so\n// the two pickers cannot come apart. What a range adds is a second segment\n// group and the dash between them.\n//\n// The date pickers page draws a range as a configuration of the *modal*\n// picker: a full-screen selector with a header and two text fields, plus a\n// modal date input variant. It carries no docked range picker and no range\n// token of its own — its token set is `docked.*` and `modal.*`, and neither\n// names a range. So the docked shape here follows the docked single picker,\n// the same choice `RangeCalendar` records for the band it draws.\n//\n// Two things are this component's own.\n//\n// **The dash is decoration, not content.** It reads as a range to someone\n// looking, and React Aria has already told a screen reader which group is\n// which — every segment is named \"Start Date\" or \"End Date\" — so repeating\n// it aloud would be a third telling. It is `aria-hidden` and takes the muted\n// role, which is what keeps it quieter than the dates either side.\n//\n// **Both segment groups and the trigger sit in one React Aria `Group`.** The\n// box draws once around all three, so a reader tabs start, end, trigger\n// rather than meeting three controls in a row.\n\ntype DateRangePickerProps<T extends DateValue> = {\n /** A function may compute the class from the picker's render state. */\n className?: RACDateRangePickerProps<T>['className'];\n /** Supporting text under the field. */\n description?: string;\n /** The message shown instead of the description, which also marks the field invalid. */\n error?: string;\n /**\n * Whether the label floats into the box's top once the field holds a\n * value, rather than sitting above it.\n * @default true\n */\n floatingLabel?: boolean;\n /** What the field is for. Always rendered; never a placeholder. */\n label: string;\n /** An icon at the box's leading end. */\n leadingIcon?: ReactNode;\n /**\n * What is drawn between the two segment groups. Decoration — a screen\n * reader is told which group is which by React Aria.\n * @default '–'\n */\n separator?: string;\n /** A function may compute the style from the picker's render state. */\n style?: RACDateRangePickerProps<T>['style'];\n /**\n * What the button that opens the calendar is called, for a screen reader.\n * @default 'Choose a date range'\n */\n triggerLabel?: string;\n /**\n * Which of the text fields page's two boxes to draw.\n * @default 'filled'\n */\n variant?: 'filled' | 'outlined';\n} & Omit<RACDateRangePickerProps<T>, 'children' | 'className' | 'style'>;\n\n/**\n * A date range typed into a field, or picked from a calendar behind a\n * button. The value is React Aria's — pass `value` with `onChange` to\n * control it, or `defaultValue` — as a `{ start, end }` pair of\n * `@internationalized/date` values from this package's `./date` subpath.\n *\n * ```tsx\n * import { CalendarDate } from '@kanso-labs/kanso-ui/date'\n *\n * <DateRangePicker\n * defaultValue={{\n * end: new CalendarDate(2026, 9, 20),\n * start: new CalendarDate(2026, 9, 15),\n * }}\n * label=\"Label\"\n * />\n * ```\n *\n * The segments are `DateField`'s and the calendar is `RangeCalendar`, so\n * `granularity`, `minValue`, `maxValue` and `isDateUnavailable` all behave\n * as they do there. Above the medium breakpoint the calendar is docked to\n * the field; below it, it opens centred, the same swap `DatePicker` makes.\n *\n * The call site's `className` and `style` land on the picker as a whole,\n * which is the element a layout positions.\n */\nfunction DateRangePicker<T extends DateValue>({\n description,\n error,\n floatingLabel = true,\n isDisabled = false,\n label,\n leadingIcon,\n separator = '–',\n triggerLabel = 'Choose a date range',\n variant = 'filled',\n ...props\n}: DateRangePickerProps<T>) {\n const validationBehavior = useFieldValidationBehavior();\n return <RACDateRangePicker<T> isDisabled={isDisabled} isInvalid={invalidFrom(error)} validationBehavior={validationBehavior} {...props} {...mergeStatefulStyles(stylex.props(fieldStyles.root), props)}>\n <FieldBox floatingLabel={floatingLabel}\n // Always populated, which buys exactly one thing: the outlined\n // notch. The box decides populated twice over — in CSS for the\n // label's type, and in React for the notch, since CSS cannot cut an\n // outline to a width it has no way to measure. React Aria renders a\n // hidden input per segment group, neither carrying a placeholder, so\n // the CSS half reads as populated on its own; the React half reads\n // React Aria's input context, which a picker does not provide.\n // Without this the notch stays shut across segments already showing\n // `mm/dd/yyyy`.\n isPopulated label={label} leading={leadingIcon} variant={variant}>\n <FieldValue>\n <RACGroup {...stylex.props(picker.group)}>\n <RACDateInput slot=\"start\" {...stylex.props(segmentStyles.input)}>\n {renderSegment}\n </RACDateInput>\n <span aria-hidden=\"true\" className=\"x1w5n3ug x2lah0s x16svsjw x1848etk xh7dzej\">\n {separator}\n </span>\n <RACDateInput slot=\"end\" {...stylex.props(segmentStyles.input)}>\n {renderSegment}\n </RACDateInput>\n <RACButton aria-label={triggerLabel} className={triggerClassName}>\n <CalendarGlyph {...stylex.props(picker.triggerGlyph)} />\n </RACButton>\n </RACGroup>\n </FieldValue>\n </FieldBox>\n <FieldMessage description={description} error={error} />\n <RACPopover {...stylex.props(overlay.popup, picker.popover)}>\n <RACDialog>\n <RangeCalendar aria-label={label} />\n </RACDialog>\n </RACPopover>\n </RACDateRangePicker>;\n}\nexport type { DateRangePickerProps };\nexport default DateRangePicker;"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAwGA,SAAS,kBAAqC,EAC5C,aACA,OACA,gBAAgB,MAChB,aAAa,OACb,OACA,aACA,YAAY,KACZ,eAAe,uBACf,UAAU,UACV,GAAG,WACuB;CAC1B,MAAM,qBAAqB,2BAA2B;CACtD,OAAO,qBAAC,iBAAD;EAAmC;EAAY,WAAW,YAAY,KAAK;EAAuB;EAAoB,GAAI;EAAO,GAAI,oBAAoB,MAAa,YAAY,IAAI,GAAG,OAAK;EAA9L,UAAA;GACH,oBAAC,UAAD;IAAyB;IAU3B,aAAA;IAAmB;IAAO,SAAS;IAAsB;IACrD,UAAA,oBAAC,YAAD,EAAA,UACE,qBAAC,OAAD;KAAU,GAAI,MAAa,OAAO,KAAK;KAAvC,UAAA;MACE,oBAAC,WAAD;OAAc,MAAK;OAAQ,GAAI,MAAa,cAAc,KAAK;OAC5D,UAAA;MACW,CAAA;MACd,oBAAC,QAAD;OAAM,eAAY;OAAO,WAAU;OAChC,UAAA;MACG,CAAA;MACN,oBAAC,WAAD;OAAc,MAAK;OAAM,GAAI,MAAa,cAAc,KAAK;OAC1D,UAAA;MACW,CAAA;MACd,oBAAC,QAAD;OAAW,cAAY;OAAc,WAAW;OAC9C,UAAA,oBAAC,eAAD,EAAe,GAAI,MAAa,OAAO,YAAY,EAAE,CAAA;MAC5C,CAAA;KACH;IACA,CAAA,EAAA,CAAA;GACJ,CAAA;GACV,oBAAC,cAAD;IAA2B;IAAoB;GAAM,CAAA;GACrD,oBAAC,SAAD;IAAY,GAAI,MAAa,QAAQ,OAAO,OAAO,OAAO;IACxD,UAAA,oBAAC,QAAD,EAAA,UACE,oBAAC,iBAAD,EAAe,cAAY,MAAM,CAAA,EACxB,CAAA;GACD,CAAA;EACM;;AACxB"}
|
|
@@ -88,7 +88,7 @@ function DisclosureHeader({ children, headingLevel = 3, leading, supporting }) {
|
|
|
88
88
|
level: headingLevel,
|
|
89
89
|
className: "x1qlqyl8 x1pd3egz x1ghz6dp",
|
|
90
90
|
children: /* @__PURE__ */ jsx(Button, {
|
|
91
|
-
className: headerClassName,
|
|
91
|
+
className: headerClassName(supporting),
|
|
92
92
|
slot: "trigger",
|
|
93
93
|
children: headerContent(children, leading, supporting, state?.isExpanded === true)
|
|
94
94
|
})
|
|
@@ -149,8 +149,8 @@ function DisclosurePanel$1(t0) {
|
|
|
149
149
|
} else t6 = $[10];
|
|
150
150
|
return t6;
|
|
151
151
|
}
|
|
152
|
-
function headerClassName(
|
|
153
|
-
return props(rowStyles.base, rowStyles.list, rowStyles.interactive, styles.header, state.isDisabled && rowStyles.disabled).className ?? "";
|
|
152
|
+
function headerClassName(supporting) {
|
|
153
|
+
return (state) => props(rowStyles.base, rowStyles.list, rowStyles.interactive, styles.header, supporting !== void 0 && rowStyles.twoLine, state.isDisabled && rowStyles.disabled).className ?? "";
|
|
154
154
|
}
|
|
155
155
|
function headerContent(children, leading, supporting, isExpanded) {
|
|
156
156
|
return (state) => /* @__PURE__ */ jsx(RowContent, {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","names":["props","children"],"sources":["../../../src/components/disclosure/index.tsx"],"sourcesContent":["import type { ReactNode } from 'react';\nimport type { DisclosurePanelProps as RACDisclosurePanelProps, DisclosureProps as RACDisclosureProps } from 'react-aria-components';\nimport * as stylex from '@stylexjs/stylex';\nimport { useContext } from 'react';\nimport { DisclosureStateContext, Button as RACButton, Disclosure as RACDisclosure, DisclosurePanel as RACDisclosurePanel, Heading as RACHeading } from 'react-aria-components';\nimport { ChevronEndGlyph } from '../../glyphs';\nimport { RowContent } from '../../row';\nimport { rowStyles } from '../../row/styles';\nimport { mergeStatefulStyles } from '../../styles/merge';\nimport '../../tokens/design.tokens.stylex';\nimport { colors, motion, spacing } from '../../tokens/design.tokens.stylex';\n\n// A section that opens to show what is under it, and closes again. The\n// header is the row every list here draws — `src/row`, shared with ListItem,\n// ListBox and List — so its 56dp floor, body-large headline, body-medium\n// supporting line and state layers are that module's, and a header sitting\n// above a list cannot drift from the rows below it.\n//\n// The lists page gives the expand interaction its own token set, which its\n// widget keeps behind a menu that does not open to a script. What the page\n// states in words covers the row, which is what the shared module already\n// carries; the chevron's size and the panel's inset below are the library's\n// own, taken from the row's own trailing slot and inline padding rather than\n// invented.\n//\n// Three things are this component's own.\n//\n// **The header is a heading with a button in it.** React Aria wants both —\n// the heading is what a screen reader jumps between, and the button is what\n// opens the section — so `Disclosure.Header` renders the pair rather than\n// leaving a call site to remember. `headingLevel` says where in the page's\n// outline it sits.\n//\n// **The panel opens to its own height, without one being measured.** A grid\n// whose single row goes from `0fr` to `1fr` interpolates between nothing and\n// the content's natural height, so no height is read from the DOM and no\n// number is written down. Under `prefers-reduced-motion` the row snaps\n// instead.\n//\n// **Only the opening animates, and that is React Aria's doing rather than a\n// choice here.** It marks the collapsed panel `hidden=\"until-found\"`, so on\n// the way closed the content stops being laid out at once and the track has\n// nothing left to shrink. Worth knowing before reaching for a closing\n// animation: it needs the panel kept in the layout, which would cost the\n// find-in-page behaviour that attribute buys.\n\nconst styles = {\n header: {\n kzqmXN: \"xh8yej3\",\n k9WMMc: \"x1yc453h\",\n $$css: true\n }\n};\ntype DisclosureHeaderProps = {\n /** The header's headline — what the section is about. */\n children?: ReactNode;\n /**\n * Where the header sits in the page's outline. React Aria renders the\n * trigger inside a heading, and a screen reader moves between them.\n * @default 3\n */\n headingLevel?: number;\n /** Content before the headline: an avatar, an icon. */\n leading?: ReactNode;\n /** A second line under the headline, in the muted role. */\n supporting?: ReactNode;\n};\ntype DisclosurePanelProps = Omit<RACDisclosurePanelProps, 'className' | 'style'> & {\n /** A function may compute the class from the panel's render state. */\n className?: RACDisclosurePanelProps['className'];\n /** A function may compute the style from the panel's render state. */\n style?: RACDisclosurePanelProps['style'];\n};\ntype DisclosureProps = Omit<RACDisclosureProps, 'children'> & {\n /** A `Disclosure.Header` and a `Disclosure.Panel`. */\n children?: ReactNode;\n};\n\n// The chevron, turned or not. A call rather than JSX written at the prop,\n// which is what react-perf's jsx-no-jsx-as-prop is after; the React Compiler\n// memoises the result on `isExpanded`.\nfunction chevronFor(isExpanded: boolean) {\n return <ChevronEndGlyph {...{\n 0: {\n className: \"xxk0z11 x1w5n3ug x2lah0s xvy4d1p x19axjrm x1c071of xkzkux9 x11xpdln xpc4ca7\"\n },\n 1: {\n className: \"xxk0z11 x1w5n3ug x2lah0s xvy4d1p xkzkux9 x11xpdln xpc4ca7 x1y10d4b x1iffjtl\"\n }\n }[!!isExpanded << 0]} />;\n}\n\n/**\n * A section that opens to show what is under it. Whether it is open is React\n * Aria's: pass `isExpanded` with `onExpandedChange` to control it, or\n * `defaultExpanded` to let it keep its own.\n *\n * ```tsx\n * <Disclosure>\n * <Disclosure.Header>Headline</Disclosure.Header>\n * <Disclosure.Panel>Supporting line</Disclosure.Panel>\n * </Disclosure>\n * ```\n *\n * The header is the row every list here draws, so a section above a list of\n * rows lines up with them. The panel opens to whatever height its content\n * turns out to have, and snaps rather than sliding under\n * `prefers-reduced-motion`.\n *\n * The call site's `className` and `style` land on the container, which is the\n * element a layout positions.\n */\nfunction Disclosure({\n children,\n ...props\n}: DisclosureProps) {\n return <RACDisclosure {...props} {...mergeStatefulStyles({\n className: \"x9f619 x78zum5 xdt5ytf\"\n }, props)}>\n {children}\n </RACDisclosure>;\n}\n\n/**\n * The row that opens the section. It renders the heading React Aria wants\n * around the trigger and the button inside it, and draws the shared row's\n * slots with a chevron in the trailing one.\n */\nfunction DisclosureHeader({\n children,\n headingLevel = 3,\n leading,\n supporting\n}: DisclosureHeaderProps) {\n // The chevron turns with the section, and React Aria's button render state\n // reports the press states rather than what the button controls — so\n // whether the section is open comes from the disclosure's own context.\n const state = useContext(DisclosureStateContext);\n return <RACHeading level={headingLevel} className=\"x1qlqyl8 x1pd3egz x1ghz6dp\">\n <RACButton className={headerClassName} slot=\"trigger\">\n {headerContent(children, leading, supporting, state?.isExpanded === true)}\n </RACButton>\n </RACHeading>;\n}\n\n/**\n * What the section shows while it is open. Its content lines up with the\n * headline above it, and it takes the group role React Aria gives it —\n * `role=\"region\"` names it in the landmark list instead, for a section a\n * reader should be able to jump to.\n */\nfunction DisclosurePanel({\n children,\n ...props\n}: DisclosurePanelProps) {\n // The track has to know, and React Aria hands the render state to the panel\n // rather than to what wraps it — so the state comes from its context, the\n // same one its own panel reads.\n const state = useContext(DisclosureStateContext);\n return <div {...{\n 0: {\n className: \"x12w9bfk xrvj5dj xihq33y xjvfotl x1qn9uv2 x1seskgd\"\n },\n 1: {\n className: \"x12w9bfk xrvj5dj xjvfotl x1qn9uv2 x1seskgd x1tu4anv\"\n }\n }[!!(state?.isExpanded === true) << 0]}>\n <RACDisclosurePanel {...props} {...mergeStatefulStyles({\n className: \"x9f619 x2lwn1j xb3r6kr\"\n }, props)}>\n <div className=\"x9f619 xzfxn0k x790zyz\">{children}</div>\n </RACDisclosurePanel>\n </div>;\n}\n\n// The trigger's classes, from React Aria's render state. `isSelected` is not\n// among them — a disclosure's button reports `aria-expanded` rather than a\n// selection — so the row draws unselected throughout and only its disabled\n// state changes.\nfunction headerClassName(state: {\n isDisabled: boolean;\n}) {\n return stylex.props(rowStyles.base, rowStyles.list, rowStyles.interactive, styles.header, state.isDisabled && rowStyles.disabled).className ?? '';\n}\n\n// What the header row draws. Built by a call rather than written inline at\n// the prop, which is what react-perf's no-new-function-as-prop is after; the\n// React Compiler memoises the result on its inputs.\nfunction headerContent(children: ReactNode, leading: ReactNode, supporting: ReactNode, isExpanded: boolean) {\n return (state: {\n isDisabled: boolean;\n }) => <RowContent isDisabled={state.isDisabled} leading={leading} supporting={supporting} trailing={chevronFor(isExpanded)}>\n {children}\n </RowContent>;\n}\nDisclosure.Header = DisclosureHeader;\nDisclosure.Panel = DisclosurePanel;\nexport type { DisclosureHeaderProps, DisclosurePanelProps, DisclosureProps };\nexport default Disclosure;"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"index.js","names":["props","children"],"sources":["../../../src/components/disclosure/index.tsx"],"sourcesContent":["import type { ReactNode } from 'react';\nimport type { DisclosurePanelProps as RACDisclosurePanelProps, DisclosureProps as RACDisclosureProps } from 'react-aria-components';\nimport * as stylex from '@stylexjs/stylex';\nimport { useContext } from 'react';\nimport { DisclosureStateContext, Button as RACButton, Disclosure as RACDisclosure, DisclosurePanel as RACDisclosurePanel, Heading as RACHeading } from 'react-aria-components';\nimport { ChevronEndGlyph } from '../../glyphs';\nimport { RowContent } from '../../row';\nimport { rowStyles } from '../../row/styles';\nimport { mergeStatefulStyles } from '../../styles/merge';\nimport '../../tokens/design.tokens.stylex';\nimport { colors, motion, spacing } from '../../tokens/design.tokens.stylex';\n\n// A section that opens to show what is under it, and closes again. The\n// header is the row every list here draws — `src/row`, shared with ListItem,\n// ListBox and List — so its 56dp floor, body-large headline, body-medium\n// supporting line and state layers are that module's, and a header sitting\n// above a list cannot drift from the rows below it.\n//\n// The lists page gives the expand interaction its own token set, which its\n// widget keeps behind a menu that does not open to a script. What the page\n// states in words covers the row, which is what the shared module already\n// carries; the chevron's size and the panel's inset below are the library's\n// own, taken from the row's own trailing slot and inline padding rather than\n// invented.\n//\n// Three things are this component's own.\n//\n// **The header is a heading with a button in it.** React Aria wants both —\n// the heading is what a screen reader jumps between, and the button is what\n// opens the section — so `Disclosure.Header` renders the pair rather than\n// leaving a call site to remember. `headingLevel` says where in the page's\n// outline it sits.\n//\n// **The panel opens to its own height, without one being measured.** A grid\n// whose single row goes from `0fr` to `1fr` interpolates between nothing and\n// the content's natural height, so no height is read from the DOM and no\n// number is written down. Under `prefers-reduced-motion` the row snaps\n// instead.\n//\n// **Only the opening animates, and that is React Aria's doing rather than a\n// choice here.** It marks the collapsed panel `hidden=\"until-found\"`, so on\n// the way closed the content stops being laid out at once and the track has\n// nothing left to shrink. Worth knowing before reaching for a closing\n// animation: it needs the panel kept in the layout, which would cost the\n// find-in-page behaviour that attribute buys.\n\nconst styles = {\n header: {\n kzqmXN: \"xh8yej3\",\n k9WMMc: \"x1yc453h\",\n $$css: true\n }\n};\ntype DisclosureHeaderProps = {\n /** The header's headline — what the section is about. */\n children?: ReactNode;\n /**\n * Where the header sits in the page's outline. React Aria renders the\n * trigger inside a heading, and a screen reader moves between them.\n * @default 3\n */\n headingLevel?: number;\n /** Content before the headline: an avatar, an icon. */\n leading?: ReactNode;\n /** A second line under the headline, in the muted role. */\n supporting?: ReactNode;\n};\ntype DisclosurePanelProps = Omit<RACDisclosurePanelProps, 'className' | 'style'> & {\n /** A function may compute the class from the panel's render state. */\n className?: RACDisclosurePanelProps['className'];\n /** A function may compute the style from the panel's render state. */\n style?: RACDisclosurePanelProps['style'];\n};\ntype DisclosureProps = Omit<RACDisclosureProps, 'children'> & {\n /** A `Disclosure.Header` and a `Disclosure.Panel`. */\n children?: ReactNode;\n};\n\n// The chevron, turned or not. A call rather than JSX written at the prop,\n// which is what react-perf's jsx-no-jsx-as-prop is after; the React Compiler\n// memoises the result on `isExpanded`.\nfunction chevronFor(isExpanded: boolean) {\n return <ChevronEndGlyph {...{\n 0: {\n className: \"xxk0z11 x1w5n3ug x2lah0s xvy4d1p x19axjrm x1c071of xkzkux9 x11xpdln xpc4ca7\"\n },\n 1: {\n className: \"xxk0z11 x1w5n3ug x2lah0s xvy4d1p xkzkux9 x11xpdln xpc4ca7 x1y10d4b x1iffjtl\"\n }\n }[!!isExpanded << 0]} />;\n}\n\n/**\n * A section that opens to show what is under it. Whether it is open is React\n * Aria's: pass `isExpanded` with `onExpandedChange` to control it, or\n * `defaultExpanded` to let it keep its own.\n *\n * ```tsx\n * <Disclosure>\n * <Disclosure.Header>Headline</Disclosure.Header>\n * <Disclosure.Panel>Supporting line</Disclosure.Panel>\n * </Disclosure>\n * ```\n *\n * The header is the row every list here draws, so a section above a list of\n * rows lines up with them. The panel opens to whatever height its content\n * turns out to have, and snaps rather than sliding under\n * `prefers-reduced-motion`.\n *\n * The call site's `className` and `style` land on the container, which is the\n * element a layout positions.\n */\nfunction Disclosure({\n children,\n ...props\n}: DisclosureProps) {\n return <RACDisclosure {...props} {...mergeStatefulStyles({\n className: \"x9f619 x78zum5 xdt5ytf\"\n }, props)}>\n {children}\n </RACDisclosure>;\n}\n\n/**\n * The row that opens the section. It renders the heading React Aria wants\n * around the trigger and the button inside it, and draws the shared row's\n * slots with a chevron in the trailing one.\n */\nfunction DisclosureHeader({\n children,\n headingLevel = 3,\n leading,\n supporting\n}: DisclosureHeaderProps) {\n // The chevron turns with the section, and React Aria's button render state\n // reports the press states rather than what the button controls — so\n // whether the section is open comes from the disclosure's own context.\n const state = useContext(DisclosureStateContext);\n return <RACHeading level={headingLevel} className=\"x1qlqyl8 x1pd3egz x1ghz6dp\">\n <RACButton className={headerClassName(supporting)} slot=\"trigger\">\n {headerContent(children, leading, supporting, state?.isExpanded === true)}\n </RACButton>\n </RACHeading>;\n}\n\n/**\n * What the section shows while it is open. Its content lines up with the\n * headline above it, and it takes the group role React Aria gives it —\n * `role=\"region\"` names it in the landmark list instead, for a section a\n * reader should be able to jump to.\n */\nfunction DisclosurePanel({\n children,\n ...props\n}: DisclosurePanelProps) {\n // The track has to know, and React Aria hands the render state to the panel\n // rather than to what wraps it — so the state comes from its context, the\n // same one its own panel reads.\n const state = useContext(DisclosureStateContext);\n return <div {...{\n 0: {\n className: \"x12w9bfk xrvj5dj xihq33y xjvfotl x1qn9uv2 x1seskgd\"\n },\n 1: {\n className: \"x12w9bfk xrvj5dj xjvfotl x1qn9uv2 x1seskgd x1tu4anv\"\n }\n }[!!(state?.isExpanded === true) << 0]}>\n <RACDisclosurePanel {...props} {...mergeStatefulStyles({\n className: \"x9f619 x2lwn1j xb3r6kr\"\n }, props)}>\n <div className=\"x9f619 xzfxn0k x790zyz\">{children}</div>\n </RACDisclosurePanel>\n </div>;\n}\n\n// The trigger's classes, from React Aria's render state. `isSelected` is not\n// among them — a disclosure's button reports `aria-expanded` rather than a\n// selection — so the row draws unselected throughout and only its disabled\n// state changes.\n//\n// A supporting line moves the header from the page's one-line container\n// height to its two-line one, which is a floor rather than something the\n// row's own box arrives at — see `twoLine` in `src/row/styles.ts`. Taken as\n// an argument rather than read from the render state, since React Aria\n// reports what the trigger is doing and not what it holds; the classes are\n// built by a call for the same reason `headerContent` is.\nfunction headerClassName(supporting: ReactNode) {\n return (state: {\n isDisabled: boolean;\n }) => stylex.props(rowStyles.base, rowStyles.list, rowStyles.interactive, styles.header, supporting !== undefined && rowStyles.twoLine, state.isDisabled && rowStyles.disabled).className ?? '';\n}\n\n// What the header row draws. Built by a call rather than written inline at\n// the prop, which is what react-perf's no-new-function-as-prop is after; the\n// React Compiler memoises the result on its inputs.\nfunction headerContent(children: ReactNode, leading: ReactNode, supporting: ReactNode, isExpanded: boolean) {\n return (state: {\n isDisabled: boolean;\n }) => <RowContent isDisabled={state.isDisabled} leading={leading} supporting={supporting} trailing={chevronFor(isExpanded)}>\n {children}\n </RowContent>;\n}\nDisclosure.Header = DisclosureHeader;\nDisclosure.Panel = DisclosurePanel;\nexport type { DisclosureHeaderProps, DisclosurePanelProps, DisclosureProps };\nexport default Disclosure;"],"mappings":"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"}
|
|
@@ -0,0 +1,60 @@
|
|
|
1
|
+
import { ReactNode } from "react";
|
|
2
|
+
import { DropZoneProps, FileTriggerProps } from "react-aria-components";
|
|
3
|
+
//#region src/components/drop-zone/index.d.ts
|
|
4
|
+
type DropZoneProps$1 = Omit<DropZoneProps, 'children' | 'className' | 'style'> & {
|
|
5
|
+
/** What the target holds: its label, and whatever else it offers. */
|
|
6
|
+
children?: ReactNode;
|
|
7
|
+
/** A function may compute the class from the target's render state. */
|
|
8
|
+
className?: DropZoneProps['className'];
|
|
9
|
+
/**
|
|
10
|
+
* What the target says it is for. Drawn inside it and used as its
|
|
11
|
+
* accessible name, so a target with one needs no `aria-label`. A string
|
|
12
|
+
* rather than a node, since it is what names the target; anything richer
|
|
13
|
+
* goes in `children` beside it.
|
|
14
|
+
*/
|
|
15
|
+
label?: string;
|
|
16
|
+
/** A function may compute the style from the target's render state. */
|
|
17
|
+
style?: DropZoneProps['style'];
|
|
18
|
+
};
|
|
19
|
+
type FileTriggerProps$1 = FileTriggerProps;
|
|
20
|
+
/**
|
|
21
|
+
* A place to drop files. What is dropped is React Aria's: `onDrop` is handed
|
|
22
|
+
* the items, and `isFileDropItem`, `isDirectoryDropItem`, `isTextDropItem`
|
|
23
|
+
* and `DIRECTORY_DRAG_TYPE` are exported from the package for reading them.
|
|
24
|
+
*
|
|
25
|
+
* ```tsx
|
|
26
|
+
* <DropZone label="Drop here" onDrop={handleDrop}>
|
|
27
|
+
* <FileTrigger onSelect={handleSelect}>
|
|
28
|
+
* <Button variant="outlined">Label</Button>
|
|
29
|
+
* </FileTrigger>
|
|
30
|
+
* </DropZone>
|
|
31
|
+
* ```
|
|
32
|
+
*
|
|
33
|
+
* It is drawn from the outlined card, with a dashed rule rather than a solid
|
|
34
|
+
* one, and fills with the primary container while something is over it.
|
|
35
|
+
* `label` both draws the words and names the target; `aria-label` names it
|
|
36
|
+
* without drawing anything, for a page that already says what it takes.
|
|
37
|
+
*
|
|
38
|
+
* The call site's `className` and `style` land on the target itself, which
|
|
39
|
+
* is the element a layout positions.
|
|
40
|
+
*/
|
|
41
|
+
declare function DropZone$1({ children, label, ...props }: DropZoneProps$1): import("react").JSX.Element;
|
|
42
|
+
/**
|
|
43
|
+
* A button that opens the file picker. Wrap whatever should open it —
|
|
44
|
+
* normally the library's Button — and take the files from `onSelect`.
|
|
45
|
+
*
|
|
46
|
+
* ```tsx
|
|
47
|
+
* <FileTrigger acceptedFileTypes={['image/*']} onSelect={handleSelect}>
|
|
48
|
+
* <Button>Label</Button>
|
|
49
|
+
* </FileTrigger>
|
|
50
|
+
* ```
|
|
51
|
+
*
|
|
52
|
+
* It renders nothing of its own but the hidden input, so it takes no
|
|
53
|
+
* `className` or `style`: what is seen is whatever it wraps. `allowsMultiple`
|
|
54
|
+
* takes more than one file, `acceptDirectory` takes a folder, and
|
|
55
|
+
* `defaultCamera` opens straight to a camera on a device that has one.
|
|
56
|
+
*/
|
|
57
|
+
declare function FileTrigger$1(props: FileTriggerProps$1): import("react").JSX.Element;
|
|
58
|
+
//#endregion
|
|
59
|
+
export { type DropZoneProps$1 as DropZoneProps, FileTrigger$1 as FileTrigger, type FileTriggerProps$1 as FileTriggerProps, DropZone$1 as default };
|
|
60
|
+
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +1,118 @@
|
|
|
1
|
+
import { props } from "../../node_modules/@stylexjs/stylex/lib/es/stylex.js";
|
|
2
|
+
import { mergeStatefulStyles } from "../../styles/merge.js";
|
|
3
|
+
import { dropZoneStyles, rootStyles } from "./styles.js";
|
|
4
|
+
import { Fragment, jsx, jsxs } from "react/jsx-runtime";
|
|
5
|
+
import { c } from "react/compiler-runtime";
|
|
6
|
+
import { DropZone, FileTrigger } from "react-aria-components";
|
|
7
|
+
//#region src/components/drop-zone/index.tsx
|
|
8
|
+
function content(children, label) {
|
|
9
|
+
return /* @__PURE__ */ jsxs(Fragment, { children: [label === void 0 ? null : /* @__PURE__ */ jsx("p", {
|
|
10
|
+
...props(dropZoneStyles.label),
|
|
11
|
+
children: label
|
|
12
|
+
}), children] });
|
|
13
|
+
}
|
|
14
|
+
/**
|
|
15
|
+
* A place to drop files. What is dropped is React Aria's: `onDrop` is handed
|
|
16
|
+
* the items, and `isFileDropItem`, `isDirectoryDropItem`, `isTextDropItem`
|
|
17
|
+
* and `DIRECTORY_DRAG_TYPE` are exported from the package for reading them.
|
|
18
|
+
*
|
|
19
|
+
* ```tsx
|
|
20
|
+
* <DropZone label="Drop here" onDrop={handleDrop}>
|
|
21
|
+
* <FileTrigger onSelect={handleSelect}>
|
|
22
|
+
* <Button variant="outlined">Label</Button>
|
|
23
|
+
* </FileTrigger>
|
|
24
|
+
* </DropZone>
|
|
25
|
+
* ```
|
|
26
|
+
*
|
|
27
|
+
* It is drawn from the outlined card, with a dashed rule rather than a solid
|
|
28
|
+
* one, and fills with the primary container while something is over it.
|
|
29
|
+
* `label` both draws the words and names the target; `aria-label` names it
|
|
30
|
+
* without drawing anything, for a page that already says what it takes.
|
|
31
|
+
*
|
|
32
|
+
* The call site's `className` and `style` land on the target itself, which
|
|
33
|
+
* is the element a layout positions.
|
|
34
|
+
*/
|
|
35
|
+
function DropZone$1(t0) {
|
|
36
|
+
const $ = c(16);
|
|
37
|
+
let T0;
|
|
38
|
+
let children;
|
|
39
|
+
let label;
|
|
40
|
+
let t1;
|
|
41
|
+
let t2;
|
|
42
|
+
let t3;
|
|
43
|
+
if ($[0] !== t0) {
|
|
44
|
+
const { children: t4, label: t5, ...props } = t0;
|
|
45
|
+
children = t4;
|
|
46
|
+
label = t5;
|
|
47
|
+
T0 = DropZone;
|
|
48
|
+
t1 = props["aria-label"] ?? label;
|
|
49
|
+
t2 = props;
|
|
50
|
+
t3 = mergeStatefulStyles(rootStyles, props);
|
|
51
|
+
$[0] = t0;
|
|
52
|
+
$[1] = T0;
|
|
53
|
+
$[2] = children;
|
|
54
|
+
$[3] = label;
|
|
55
|
+
$[4] = t1;
|
|
56
|
+
$[5] = t2;
|
|
57
|
+
$[6] = t3;
|
|
58
|
+
} else {
|
|
59
|
+
T0 = $[1];
|
|
60
|
+
children = $[2];
|
|
61
|
+
label = $[3];
|
|
62
|
+
t1 = $[4];
|
|
63
|
+
t2 = $[5];
|
|
64
|
+
t3 = $[6];
|
|
65
|
+
}
|
|
66
|
+
let t4;
|
|
67
|
+
if ($[7] !== children || $[8] !== label) {
|
|
68
|
+
t4 = content(children, label);
|
|
69
|
+
$[7] = children;
|
|
70
|
+
$[8] = label;
|
|
71
|
+
$[9] = t4;
|
|
72
|
+
} else t4 = $[9];
|
|
73
|
+
let t5;
|
|
74
|
+
if ($[10] !== T0 || $[11] !== t1 || $[12] !== t2 || $[13] !== t3 || $[14] !== t4) {
|
|
75
|
+
t5 = /* @__PURE__ */ jsx(T0, {
|
|
76
|
+
"aria-label": t1,
|
|
77
|
+
...t2,
|
|
78
|
+
...t3,
|
|
79
|
+
children: t4
|
|
80
|
+
});
|
|
81
|
+
$[10] = T0;
|
|
82
|
+
$[11] = t1;
|
|
83
|
+
$[12] = t2;
|
|
84
|
+
$[13] = t3;
|
|
85
|
+
$[14] = t4;
|
|
86
|
+
$[15] = t5;
|
|
87
|
+
} else t5 = $[15];
|
|
88
|
+
return t5;
|
|
89
|
+
}
|
|
90
|
+
/**
|
|
91
|
+
* A button that opens the file picker. Wrap whatever should open it —
|
|
92
|
+
* normally the library's Button — and take the files from `onSelect`.
|
|
93
|
+
*
|
|
94
|
+
* ```tsx
|
|
95
|
+
* <FileTrigger acceptedFileTypes={['image/*']} onSelect={handleSelect}>
|
|
96
|
+
* <Button>Label</Button>
|
|
97
|
+
* </FileTrigger>
|
|
98
|
+
* ```
|
|
99
|
+
*
|
|
100
|
+
* It renders nothing of its own but the hidden input, so it takes no
|
|
101
|
+
* `className` or `style`: what is seen is whatever it wraps. `allowsMultiple`
|
|
102
|
+
* takes more than one file, `acceptDirectory` takes a folder, and
|
|
103
|
+
* `defaultCamera` opens straight to a camera on a device that has one.
|
|
104
|
+
*/
|
|
105
|
+
function FileTrigger$1(props) {
|
|
106
|
+
const $ = c(2);
|
|
107
|
+
let t0;
|
|
108
|
+
if ($[0] !== props) {
|
|
109
|
+
t0 = /* @__PURE__ */ jsx(FileTrigger, { ...props });
|
|
110
|
+
$[0] = props;
|
|
111
|
+
$[1] = t0;
|
|
112
|
+
} else t0 = $[1];
|
|
113
|
+
return t0;
|
|
114
|
+
}
|
|
115
|
+
//#endregion
|
|
116
|
+
export { FileTrigger$1 as FileTrigger, DropZone$1 as default };
|
|
117
|
+
|
|
118
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","names":["props"],"sources":["../../../src/components/drop-zone/index.tsx"],"sourcesContent":["import type { ReactNode } from 'react';\nimport type { DropZoneProps as RACDropZoneProps, FileTriggerProps as RACFileTriggerProps } from 'react-aria-components';\nimport * as stylex from '@stylexjs/stylex';\nimport { DropZone as RACDropZone, FileTrigger as RACFileTrigger } from 'react-aria-components';\nimport { mergeStatefulStyles } from '../../styles/merge';\nimport { dropZoneStyles, rootStyles } from './styles';\n\n// A place to drop files, and a button that opens the file picker. The design\n// system carries no page for either — there is no drop target and no file\n// input in it — so the drop target is drawn from the nearest thing it does\n// carry, the outlined card: the same surface, the same 1dp outline-variant\n// rule and the same medium corner.\n//\n// Two departures from that card, both this component's own.\n//\n// **The rule is dashed rather than solid.** A solid rule reads as a card,\n// which is a thing that holds content; a dashed one reads as a place to put\n// something, which is what this is. It is the one convention strong enough\n// that drawing it as a card would be the surprising choice.\n//\n// **Dropping over it fills it.** The rule goes to the primary role and the\n// surface to primary container, which is the same pair a selected list row\n// takes — so \"this is the target\" looks the same here as \"this is the one\n// chosen\" does elsewhere.\n//\n// **The label names the target rather than being composed into a name.**\n// React Aria puts a visually hidden button inside and, given nothing, labels\n// it `DropZone` — its own component name, untranslated, which is what a\n// screen reader would then read out. Passing the label through as the\n// button's `aria-label` and drawing the text as ordinary content is what\n// makes the name the words the call site wrote and nothing else; React\n// Aria's own label slot would compose the two and say both.\n//\n// `FileTrigger` is beside it rather than inside it, and that is React Aria's\n// shape rather than a choice here: a file picker is useful on its own, with\n// no drop target anywhere near it. It renders nothing but a hidden input, so\n// it takes no `className` or `style` of its own — whatever it wraps is what\n// is seen, and that is normally the library's Button.\n\ntype DropZoneProps = Omit<RACDropZoneProps, 'children' | 'className' | 'style'> & {\n /** What the target holds: its label, and whatever else it offers. */\n children?: ReactNode;\n /** A function may compute the class from the target's render state. */\n className?: RACDropZoneProps['className'];\n /**\n * What the target says it is for. Drawn inside it and used as its\n * accessible name, so a target with one needs no `aria-label`. A string\n * rather than a node, since it is what names the target; anything richer\n * goes in `children` beside it.\n */\n label?: string;\n /** A function may compute the style from the target's render state. */\n style?: RACDropZoneProps['style'];\n};\ntype FileTriggerProps = RACFileTriggerProps;\n\n// What the target draws, from React Aria's render state. Written as a call\n// rather than inline at the prop, which is what react-perf's\n// no-new-function-as-prop is after; the React Compiler memoises the result\n// on its inputs.\nfunction content(children: ReactNode, label: string | undefined) {\n return <>\n {label === undefined ? null : <p {...stylex.props(dropZoneStyles.label)}>{label}</p>}\n {children}\n </>;\n}\n\n/**\n * A place to drop files. What is dropped is React Aria's: `onDrop` is handed\n * the items, and `isFileDropItem`, `isDirectoryDropItem`, `isTextDropItem`\n * and `DIRECTORY_DRAG_TYPE` are exported from the package for reading them.\n *\n * ```tsx\n * <DropZone label=\"Drop here\" onDrop={handleDrop}>\n * <FileTrigger onSelect={handleSelect}>\n * <Button variant=\"outlined\">Label</Button>\n * </FileTrigger>\n * </DropZone>\n * ```\n *\n * It is drawn from the outlined card, with a dashed rule rather than a solid\n * one, and fills with the primary container while something is over it.\n * `label` both draws the words and names the target; `aria-label` names it\n * without drawing anything, for a page that already says what it takes.\n *\n * The call site's `className` and `style` land on the target itself, which\n * is the element a layout positions.\n */\nfunction DropZone({\n children,\n label,\n ...props\n}: DropZoneProps) {\n return <RACDropZone aria-label={props['aria-label'] ?? label} {...props} {...mergeStatefulStyles(rootStyles, props)}>\n {content(children, label)}\n </RACDropZone>;\n}\n\n/**\n * A button that opens the file picker. Wrap whatever should open it —\n * normally the library's Button — and take the files from `onSelect`.\n *\n * ```tsx\n * <FileTrigger acceptedFileTypes={['image/*']} onSelect={handleSelect}>\n * <Button>Label</Button>\n * </FileTrigger>\n * ```\n *\n * It renders nothing of its own but the hidden input, so it takes no\n * `className` or `style`: what is seen is whatever it wraps. `allowsMultiple`\n * takes more than one file, `acceptDirectory` takes a folder, and\n * `defaultCamera` opens straight to a camera on a device that has one.\n */\nfunction FileTrigger(props: FileTriggerProps) {\n return <RACFileTrigger {...props} />;\n}\nexport type { DropZoneProps, FileTriggerProps };\nexport { FileTrigger };\nexport default DropZone;"],"mappings":";;;;;;;AA4DA,SAAS,QAAQ,UAAqB,OAA2B;CAC/D,OAAO,qBAAA,UAAA,EAAA,UAAA,CACF,UAAU,KAAA,IAAY,OAAO,oBAAC,KAAD;EAAG,GAAI,MAAa,eAAe,KAAK;EAAI,UAAA;CAAS,CAAA,GAClF,QACH,EAAA,CAAA;AACJ;;;;;;;;;;;;;;;;;;;;;;AAuBA,SAAA,WAAA,IAAA;CAAA,MAAA,IAAA,EAAA,EAAA;CAAA,IAAA;CAAA,IAAA;CAAA,IAAA;CAAA,IAAA;CAAA,IAAA;CAAA,IAAA;CAAA,IAAA,EAAA,OAAA,IAAA;EAAkB,MAAA,EAAA,UAAA,IAAA,OAAA,IAAA,GAAA,UAAA;EAAA,WAAA;EAAA,QAAA;EAKR,KAAA;EAAwB,KAAA,MAAM,iBAAN;EAAkCA,KAAA;EAAW,KAAA,oBAAoB,YAAY,KAAK;EAAC,EAAA,KAAA;EAAA,EAAA,KAAA;EAAA,EAAA,KAAA;EAAA,EAAA,KAAA;EAAA,EAAA,KAAA;EAAA,EAAA,KAAA;EAAA,EAAA,KAAA;CAAA,OAAA;EAAA,KAAA,EAAA;EAAA,WAAA,EAAA;EAAA,QAAA,EAAA;EAAA,KAAA,EAAA;EAAA,KAAA,EAAA;EAAA,KAAA,EAAA;CAAA;CAAA,IAAA;CAAA,IAAA,EAAA,OAAA,YAAA,EAAA,OAAA,OAAA;EAC9G,KAAA,QAAQ,UAAU,KAAK;EAAC,EAAA,KAAA;EAAA,EAAA,KAAA;EAAA,EAAA,KAAA;CAAA,OAAA,KAAA,EAAA;CAAA,IAAA;CAAA,IAAA,EAAA,QAAA,MAAA,EAAA,QAAA,MAAA,EAAA,QAAA,MAAA,EAAA,QAAA,MAAA,EAAA,QAAA,IAAA;EADtB,KAAA,oBAAC,IAAD;GAAyB,cAAA;GAA4B,GAAMA;GAAK,GAAM;GACxE,UAAA;EADc,CAAA;EAEH,EAAA,MAAA;EAAA,EAAA,MAAA;EAAA,EAAA,MAAA;EAAA,EAAA,MAAA;EAAA,EAAA,MAAA;EAAA,EAAA,MAAA;CAAA,OAAA,KAAA,EAAA;CAAA,OAFT;AAES;;;;;;;;;;;;;;;;AAkBlB,SAAA,cAAA,OAAA;CAAA,MAAA,IAAA,EAAA,CAAA;CAAA,IAAA;CAAA,IAAA,EAAA,OAAA,OAAA;EACS,KAAA,oBAAC,aAAD,EAAe,GAAK,MAAK,CAAA;EAAI,EAAA,KAAA;EAAA,EAAA,KAAA;CAAA,OAAA,KAAA,EAAA;CAAA,OAA7B;AAA6B"}
|
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
//#region src/components/drop-zone/styles.ts
|
|
2
|
+
const dropZoneStyles = {
|
|
3
|
+
label: {
|
|
4
|
+
kMwMTN: "x1w5n3ug",
|
|
5
|
+
kMv6JI: "xpo2rfv",
|
|
6
|
+
kGuDYH: "x193rfdd",
|
|
7
|
+
k63SB2: "x1hews6w",
|
|
8
|
+
kb6lSQ: "xn43zvd",
|
|
9
|
+
kLWn49: "xv61bfh",
|
|
10
|
+
kogj98: "x1ghz6dp",
|
|
11
|
+
k9WMMc: "x2b8uid",
|
|
12
|
+
$$css: true
|
|
13
|
+
},
|
|
14
|
+
root: {
|
|
15
|
+
kGNEyG: "x6s0dn4",
|
|
16
|
+
kWkggS: "x14s9m32",
|
|
17
|
+
kVAM5u: "x133yhug",
|
|
18
|
+
kaIpWk: "x62ce2h",
|
|
19
|
+
ksu8eU: "xbsl7fq",
|
|
20
|
+
kMzoRj: "xmkeg23",
|
|
21
|
+
kB7OPa: "x9f619",
|
|
22
|
+
kMwMTN: "x139gbkf",
|
|
23
|
+
k1xSpc: "x78zum5",
|
|
24
|
+
kXwgrk: "xdt5ytf",
|
|
25
|
+
kOIVth: "x1gka490",
|
|
26
|
+
kjj79g: "xl56j7k",
|
|
27
|
+
kAzted: "x1db3i3o",
|
|
28
|
+
kjBf7l: "xrgy624",
|
|
29
|
+
kInvED: "x2ssjo2",
|
|
30
|
+
k3XXqK: "x1t137rt",
|
|
31
|
+
kMeerF: "x1de99jn",
|
|
32
|
+
kmVPX3: "x1apw6a7",
|
|
33
|
+
kIyJzY: "xkzkux9",
|
|
34
|
+
k1ekBW: "xts7igz",
|
|
35
|
+
kAMwcw: "xpc4ca7",
|
|
36
|
+
$$css: true
|
|
37
|
+
},
|
|
38
|
+
rootFocused: {
|
|
39
|
+
k3XXqK: "xaatb59",
|
|
40
|
+
$$css: true
|
|
41
|
+
},
|
|
42
|
+
rootOver: {
|
|
43
|
+
kWkggS: "xp89om9",
|
|
44
|
+
kVAM5u: "x1uajy3w",
|
|
45
|
+
ksu8eU: "x1y0btm7",
|
|
46
|
+
kMwMTN: "xscdzaa",
|
|
47
|
+
$$css: true
|
|
48
|
+
}
|
|
49
|
+
};
|
|
50
|
+
function rootStyles(state) {
|
|
51
|
+
return {
|
|
52
|
+
0: { className: "x6s0dn4 x14s9m32 x133yhug x62ce2h xbsl7fq xmkeg23 x9f619 x139gbkf x78zum5 xdt5ytf x1gka490 xl56j7k x1db3i3o xrgy624 x2ssjo2 x1t137rt x1de99jn x1apw6a7 xkzkux9 xts7igz xpc4ca7" },
|
|
53
|
+
2: { className: "x6s0dn4 x14s9m32 x133yhug x62ce2h xbsl7fq xmkeg23 x9f619 x139gbkf x78zum5 xdt5ytf x1gka490 xl56j7k x1db3i3o xrgy624 x2ssjo2 x1de99jn x1apw6a7 xkzkux9 xts7igz xpc4ca7 xaatb59" },
|
|
54
|
+
1: { className: "x6s0dn4 x62ce2h xmkeg23 x9f619 x78zum5 xdt5ytf x1gka490 xl56j7k x1db3i3o xrgy624 x2ssjo2 x1t137rt x1de99jn x1apw6a7 xkzkux9 xts7igz xpc4ca7 xp89om9 x1uajy3w x1y0btm7 xscdzaa" },
|
|
55
|
+
3: { className: "x6s0dn4 x62ce2h xmkeg23 x9f619 x78zum5 xdt5ytf x1gka490 xl56j7k x1db3i3o xrgy624 x2ssjo2 x1de99jn x1apw6a7 xkzkux9 xts7igz xpc4ca7 xaatb59 xp89om9 x1uajy3w x1y0btm7 xscdzaa" }
|
|
56
|
+
}[!!state.isFocusVisible << 1 | !!state.isDropTarget << 0];
|
|
57
|
+
}
|
|
58
|
+
//#endregion
|
|
59
|
+
export { dropZoneStyles, rootStyles };
|
|
60
|
+
|
|
61
|
+
//# sourceMappingURL=styles.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"styles.js","names":[],"sources":["../../../src/components/drop-zone/styles.ts"],"sourcesContent":["import * as stylex from '@stylexjs/stylex';\nimport '../../tokens/design.tokens.stylex';\nimport { colors, motion, radii, spacing, typography } from '../../tokens/design.tokens.stylex';\n\n// Apart from ./index.tsx so that file exports components alone, which is what\n// keeps fast refresh working for it — the same arrangement `src/row` uses.\n// `rootStyles` is here for a second reason: index.test.tsx applies it\n// directly, because React Aria enters `isDropTarget` only inside a real drag\n// session that a synthetic DragEvent does not start.\n\nconst dropZoneStyles = {\n label: {\n kMwMTN: \"x1w5n3ug\",\n kMv6JI: \"xpo2rfv\",\n kGuDYH: \"x193rfdd\",\n k63SB2: \"x1hews6w\",\n kb6lSQ: \"xn43zvd\",\n kLWn49: \"xv61bfh\",\n kogj98: \"x1ghz6dp\",\n k9WMMc: \"x2b8uid\",\n $$css: true\n },\n root: {\n kGNEyG: \"x6s0dn4\",\n kWkggS: \"x14s9m32\",\n kVAM5u: \"x133yhug\",\n kaIpWk: \"x62ce2h\",\n ksu8eU: \"xbsl7fq\",\n kMzoRj: \"xmkeg23\",\n kB7OPa: \"x9f619\",\n kMwMTN: \"x139gbkf\",\n k1xSpc: \"x78zum5\",\n kXwgrk: \"xdt5ytf\",\n kOIVth: \"x1gka490\",\n kjj79g: \"xl56j7k\",\n kAzted: \"x1db3i3o\",\n kjBf7l: \"xrgy624\",\n kInvED: \"x2ssjo2\",\n k3XXqK: \"x1t137rt\",\n kMeerF: \"x1de99jn\",\n kmVPX3: \"x1apw6a7\",\n kIyJzY: \"xkzkux9\",\n k1ekBW: \"xts7igz\",\n kAMwcw: \"xpc4ca7\",\n $$css: true\n },\n rootFocused: {\n k3XXqK: \"xaatb59\",\n $$css: true\n },\n rootOver: {\n kWkggS: \"xp89om9\",\n kVAM5u: \"x1uajy3w\",\n ksu8eU: \"x1y0btm7\",\n kMwMTN: \"xscdzaa\",\n $$css: true\n }\n};\n\n// The target's own classes, from React Aria's render state.\nfunction rootStyles(state: {\n isDropTarget: boolean;\n isFocusVisible: boolean;\n}) {\n return {\n 0: {\n className: \"x6s0dn4 x14s9m32 x133yhug x62ce2h xbsl7fq xmkeg23 x9f619 x139gbkf x78zum5 xdt5ytf x1gka490 xl56j7k x1db3i3o xrgy624 x2ssjo2 x1t137rt x1de99jn x1apw6a7 xkzkux9 xts7igz xpc4ca7\"\n },\n 2: {\n className: \"x6s0dn4 x14s9m32 x133yhug x62ce2h xbsl7fq xmkeg23 x9f619 x139gbkf x78zum5 xdt5ytf x1gka490 xl56j7k x1db3i3o xrgy624 x2ssjo2 x1de99jn x1apw6a7 xkzkux9 xts7igz xpc4ca7 xaatb59\"\n },\n 1: {\n className: \"x6s0dn4 x62ce2h xmkeg23 x9f619 x78zum5 xdt5ytf x1gka490 xl56j7k x1db3i3o xrgy624 x2ssjo2 x1t137rt x1de99jn x1apw6a7 xkzkux9 xts7igz xpc4ca7 xp89om9 x1uajy3w x1y0btm7 xscdzaa\"\n },\n 3: {\n className: \"x6s0dn4 x62ce2h xmkeg23 x9f619 x78zum5 xdt5ytf x1gka490 xl56j7k x1db3i3o xrgy624 x2ssjo2 x1de99jn x1apw6a7 xkzkux9 xts7igz xpc4ca7 xaatb59 xp89om9 x1uajy3w x1y0btm7 xscdzaa\"\n }\n }[!!state.isFocusVisible << 1 | !!state.isDropTarget << 0];\n}\nexport { dropZoneStyles, rootStyles };"],"mappings":";AAUA,MAAM,iBAAiB;CACrB,OAAO;EACL,QAAQ;EACR,QAAQ;EACR,QAAQ;EACR,QAAQ;EACR,QAAQ;EACR,QAAQ;EACR,QAAQ;EACR,QAAQ;EACR,OAAO;CACT;CACA,MAAM;EACJ,QAAQ;EACR,QAAQ;EACR,QAAQ;EACR,QAAQ;EACR,QAAQ;EACR,QAAQ;EACR,QAAQ;EACR,QAAQ;EACR,QAAQ;EACR,QAAQ;EACR,QAAQ;EACR,QAAQ;EACR,QAAQ;EACR,QAAQ;EACR,QAAQ;EACR,QAAQ;EACR,QAAQ;EACR,QAAQ;EACR,QAAQ;EACR,QAAQ;EACR,QAAQ;EACR,OAAO;CACT;CACA,aAAa;EACX,QAAQ;EACR,OAAO;CACT;CACA,UAAU;EACR,QAAQ;EACR,QAAQ;EACR,QAAQ;EACR,QAAQ;EACR,OAAO;CACT;AACF;AAGA,SAAS,WAAW,OAGjB;CACD,OAAO;EACL,GAAG,EACD,WAAW,iLACb;EACA,GAAG,EACD,WAAW,gLACb;EACA,GAAG,EACD,WAAW,gLACb;EACA,GAAG,EACD,WAAW,+KACb;CACF,EAAE,CAAC,CAAC,MAAM,kBAAkB,IAAI,CAAC,CAAC,MAAM,gBAAgB;AAC1D"}
|
|
@@ -68,8 +68,9 @@ type IconButtonProps = {
|
|
|
68
68
|
/** The link's `target`, when `href` is set. */
|
|
69
69
|
target?: string;
|
|
70
70
|
/**
|
|
71
|
-
* `standard` is transparent and tints what it sits on; `
|
|
72
|
-
*
|
|
71
|
+
* `standard` is transparent and tints what it sits on; `outlined` is
|
|
72
|
+
* transparent with a rule around it; `filled` and `tonal` carry a container
|
|
73
|
+
* of their own.
|
|
73
74
|
* @default 'standard'
|
|
74
75
|
*/
|
|
75
76
|
variant?: IconButtonVariant;
|
|
@@ -78,7 +79,7 @@ type IconButtonSize = 'lg' | 'md' | 'xl' | 'xs' | 'xxl';
|
|
|
78
79
|
type IconButtonState = ButtonState & {
|
|
79
80
|
isSelected?: boolean;
|
|
80
81
|
};
|
|
81
|
-
type IconButtonVariant = 'filled' | 'standard' | 'tonal';
|
|
82
|
+
type IconButtonVariant = 'filled' | 'outlined' | 'standard' | 'tonal';
|
|
82
83
|
/**
|
|
83
84
|
* A button that is an icon, at five control heights. Given `href` it is a
|
|
84
85
|
* link with the same appearance. Every `aria-*` prop is forwarded to the
|