@stonedogcode/style 0.9.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/LICENSE +201 -0
- package/NOTICE +18 -0
- package/README.md +699 -0
- package/package.json +95 -0
- package/src/components/DictationControls.tsx +141 -0
- package/src/components/DictationPrompt.tsx +78 -0
- package/src/components/StyledBox.tsx +174 -0
- package/src/components/StyledButton.tsx +144 -0
- package/src/components/StyledCollapsible.tsx +127 -0
- package/src/components/StyledDefinitionList.tsx +134 -0
- package/src/components/StyledFieldset.tsx +157 -0
- package/src/components/StyledFlex.tsx +13 -0
- package/src/components/StyledFooter.tsx +399 -0
- package/src/components/StyledFormLabel.tsx +141 -0
- package/src/components/StyledGrid.tsx +109 -0
- package/src/components/StyledGridItem.tsx +19 -0
- package/src/components/StyledHStack.tsx +145 -0
- package/src/components/StyledHeading.tsx +79 -0
- package/src/components/StyledHrRule.tsx +33 -0
- package/src/components/StyledIcon.tsx +172 -0
- package/src/components/StyledIconButton.tsx +135 -0
- package/src/components/StyledInputBool.tsx +81 -0
- package/src/components/StyledInputRadio.tsx +141 -0
- package/src/components/StyledInputSelect.tsx +115 -0
- package/src/components/StyledInputSlider.tsx +83 -0
- package/src/components/StyledInputText.tsx +146 -0
- package/src/components/StyledInputTextArea.tsx +119 -0
- package/src/components/StyledInputToggle.tsx +224 -0
- package/src/components/StyledList.tsx +188 -0
- package/src/components/StyledScrollbar.tsx +53 -0
- package/src/components/StyledSearch.tsx +78 -0
- package/src/components/StyledSeparator.tsx +38 -0
- package/src/components/StyledSidebar.tsx +555 -0
- package/src/components/StyledSimpleGrid.tsx +99 -0
- package/src/components/StyledSparkLine.tsx +119 -0
- package/src/components/StyledSpinner.tsx +91 -0
- package/src/components/StyledStack.tsx +62 -0
- package/src/components/StyledText.tsx +99 -0
- package/src/components/StyledTooltip.tsx +398 -0
- package/src/components/StyledVStack.tsx +143 -0
- package/src/components/TitleLogo.tsx +223 -0
- package/src/components/create-icon.tsx +66 -0
- package/src/components/create-intent-button.tsx +134 -0
- package/src/components/dictation.ts +71 -0
- package/src/components/intent-buttons.ts +154 -0
- package/src/config/can-hover.ts +75 -0
- package/src/config/density.ts +138 -0
- package/src/config/font-size.ts +113 -0
- package/src/config/intent-icons.tsx +116 -0
- package/src/config/logger.ts +60 -0
- package/src/config/style-config.tsx +263 -0
- package/src/config/types.ts +137 -0
- package/src/index.ts +259 -0
- package/src/preset/index.ts +243 -0
- package/src/preset/recipes/arrows.ts +29 -0
- package/src/preset/recipes/box.ts +122 -0
- package/src/preset/recipes/button.ts +161 -0
- package/src/preset/recipes/dl-list.ts +109 -0
- package/src/preset/recipes/drawer.ts +125 -0
- package/src/preset/recipes/form.ts +95 -0
- package/src/preset/recipes/icon-button.ts +161 -0
- package/src/preset/recipes/icon.ts +34 -0
- package/src/preset/recipes/input-bool.ts +184 -0
- package/src/preset/recipes/input-dropdown.ts +93 -0
- package/src/preset/recipes/input-radio.ts +158 -0
- package/src/preset/recipes/input-surface.ts +152 -0
- package/src/preset/recipes/input-text.ts +17 -0
- package/src/preset/recipes/list.ts +196 -0
- package/src/preset/recipes/menu.ts +28 -0
- package/src/preset/recipes/separator.ts +89 -0
- package/src/preset/recipes/stack.ts +89 -0
- package/src/preset/recipes/striped.ts +34 -0
- package/src/preset/recipes/text.ts +41 -0
- package/src/preset/recipes/tooltip.ts +77 -0
- package/src/preset/semantic-variables.ts +283 -0
|
@@ -0,0 +1,127 @@
|
|
|
1
|
+
"use client";
|
|
2
|
+
|
|
3
|
+
import React, { useId, useState } from "react";
|
|
4
|
+
import { styled } from "styled-system/jsx";
|
|
5
|
+
|
|
6
|
+
/**
|
|
7
|
+
* A disclosure: a trigger that shows and hides a region.
|
|
8
|
+
*
|
|
9
|
+
* Built here rather than in an app because three products want the same thing
|
|
10
|
+
* and one of them currently reaches for Chakra to get it. It knows nothing
|
|
11
|
+
* about what it contains.
|
|
12
|
+
*
|
|
13
|
+
* ## Why the content stays mounted
|
|
14
|
+
*
|
|
15
|
+
* Collapsed content is hidden with `hidden`, not unmounted. Unmounting looks
|
|
16
|
+
* tidier and is wrong for the audience this package serves: it discards focus,
|
|
17
|
+
* scroll position and any input a reader had part-typed, so a mis-click on the
|
|
18
|
+
* trigger destroys work rather than merely hiding it. `hidden` also keeps the
|
|
19
|
+
* region addressable by `aria-controls` at all times, which is what lets the
|
|
20
|
+
* trigger's `aria-expanded` mean anything.
|
|
21
|
+
*
|
|
22
|
+
* `hidden` rather than `display: none` in CSS: it is the accessibility default,
|
|
23
|
+
* it removes the content from the accessibility tree *and* from tab order in
|
|
24
|
+
* one attribute, and it cannot be defeated by a host stylesheet the way a
|
|
25
|
+
* utility class can.
|
|
26
|
+
*/
|
|
27
|
+
|
|
28
|
+
export interface StyledCollapsibleProps {
|
|
29
|
+
/** The disclosure's own control. Rendered inside a `<button>`. */
|
|
30
|
+
trigger: React.ReactNode;
|
|
31
|
+
children: React.ReactNode;
|
|
32
|
+
/** Controlled. Omit to let the component own the state. */
|
|
33
|
+
open?: boolean | undefined;
|
|
34
|
+
/** Initial state when uncontrolled. Default `false`. */
|
|
35
|
+
defaultOpen?: boolean | undefined;
|
|
36
|
+
onOpenChange?: ((next: boolean) => void) | undefined;
|
|
37
|
+
/**
|
|
38
|
+
* Names the trigger.
|
|
39
|
+
*
|
|
40
|
+
* State belongs in `aria-expanded`, never in the name — a name that reads
|
|
41
|
+
* "Collapse tools" is announced as "Collapse tools, expanded", which says the
|
|
42
|
+
* same thing twice and in opposite tenses. Say what the control is *for*.
|
|
43
|
+
*/
|
|
44
|
+
"aria-label"?: string | undefined;
|
|
45
|
+
/** Escape hatch for a host that must reach the trigger in a test. */
|
|
46
|
+
triggerTestId?: string | undefined;
|
|
47
|
+
contentTestId?: string | undefined;
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
/**
|
|
51
|
+
* 48px, matching every other interactive floor in this package: stated as a
|
|
52
|
+
* minimum rather than left to emerge from padding, so no density step or font
|
|
53
|
+
* profile can erode it below the WCAG target size.
|
|
54
|
+
*/
|
|
55
|
+
const CONTROL_MIN_TARGET = "48px";
|
|
56
|
+
|
|
57
|
+
const CollapsibleTrigger = styled("button", {
|
|
58
|
+
base: {
|
|
59
|
+
display: "inline-flex",
|
|
60
|
+
alignItems: "center",
|
|
61
|
+
gap: "2",
|
|
62
|
+
minHeight: CONTROL_MIN_TARGET,
|
|
63
|
+
minWidth: CONTROL_MIN_TARGET,
|
|
64
|
+
px: "2",
|
|
65
|
+
borderRadius: "md",
|
|
66
|
+
borderWidth: "1px",
|
|
67
|
+
borderStyle: "solid",
|
|
68
|
+
borderColor: "borderBgPrimary",
|
|
69
|
+
color: "textPrimary",
|
|
70
|
+
background: "transparent",
|
|
71
|
+
cursor: "pointer",
|
|
72
|
+
},
|
|
73
|
+
});
|
|
74
|
+
|
|
75
|
+
const StyledCollapsible: React.FC<StyledCollapsibleProps> = ({
|
|
76
|
+
trigger,
|
|
77
|
+
children,
|
|
78
|
+
open,
|
|
79
|
+
defaultOpen = false,
|
|
80
|
+
onOpenChange,
|
|
81
|
+
"aria-label": ariaLabel,
|
|
82
|
+
triggerTestId,
|
|
83
|
+
contentTestId,
|
|
84
|
+
}) => {
|
|
85
|
+
const [uncontrolled, setUncontrolled] = useState(defaultOpen);
|
|
86
|
+
|
|
87
|
+
// Controlled the moment `open` is supplied, and uncontrolled otherwise —
|
|
88
|
+
// decided per render rather than latched at mount, because a host that
|
|
89
|
+
// switches between the two mid-life has a bug we should not paper over by
|
|
90
|
+
// silently ignoring the prop.
|
|
91
|
+
const isControlled = open !== undefined;
|
|
92
|
+
const isOpen = isControlled ? open : uncontrolled;
|
|
93
|
+
|
|
94
|
+
const contentId = useId();
|
|
95
|
+
|
|
96
|
+
const toggle = () => {
|
|
97
|
+
const next = !isOpen;
|
|
98
|
+
// The internal state moves even when controlled. If the host ignores the
|
|
99
|
+
// callback the component would otherwise appear dead to the pointer, and a
|
|
100
|
+
// control that does nothing when pressed is indistinguishable from a broken
|
|
101
|
+
// one — for this audience, the reader concludes the app is broken, not that
|
|
102
|
+
// they misread the affordance.
|
|
103
|
+
if (!isControlled) setUncontrolled(next);
|
|
104
|
+
onOpenChange?.(next);
|
|
105
|
+
};
|
|
106
|
+
|
|
107
|
+
return (
|
|
108
|
+
<>
|
|
109
|
+
<CollapsibleTrigger
|
|
110
|
+
type="button"
|
|
111
|
+
onClick={toggle}
|
|
112
|
+
aria-expanded={isOpen}
|
|
113
|
+
aria-controls={contentId}
|
|
114
|
+
aria-label={ariaLabel}
|
|
115
|
+
data-testid={triggerTestId}
|
|
116
|
+
>
|
|
117
|
+
{trigger}
|
|
118
|
+
</CollapsibleTrigger>
|
|
119
|
+
<div id={contentId} hidden={!isOpen} data-testid={contentTestId}>
|
|
120
|
+
{children}
|
|
121
|
+
</div>
|
|
122
|
+
</>
|
|
123
|
+
);
|
|
124
|
+
};
|
|
125
|
+
|
|
126
|
+
export default StyledCollapsible;
|
|
127
|
+
export { StyledCollapsible };
|
|
@@ -0,0 +1,134 @@
|
|
|
1
|
+
"use client";
|
|
2
|
+
|
|
3
|
+
import React from "react";
|
|
4
|
+
import { styled } from "styled-system/jsx";
|
|
5
|
+
import { dlRecipe } from "styled-system/recipes";
|
|
6
|
+
import { useResolvedVariant } from "../config/style-config";
|
|
7
|
+
import { ALL_VARIANTS, type AllowedVariant } from "../config/types";
|
|
8
|
+
|
|
9
|
+
/**
|
|
10
|
+
* Term-and-definition pairs in two columns — the shape a details panel wants.
|
|
11
|
+
*
|
|
12
|
+
* `<dl>` rather than a table because these are *pairs*, not a grid: there is
|
|
13
|
+
* one value per label, no column headers, and nothing to sort. A screen reader
|
|
14
|
+
* announces "list, 6 items" and reads each term with its definition, which a
|
|
15
|
+
* two-column table of unheaded cells does not.
|
|
16
|
+
*
|
|
17
|
+
* ```tsx
|
|
18
|
+
* <StyledDefinitionList.Root>
|
|
19
|
+
* <StyledDefinitionList.Term>Admitted</StyledDefinitionList.Term>
|
|
20
|
+
* <StyledDefinitionList.Definition>4 March</StyledDefinitionList.Definition>
|
|
21
|
+
* </StyledDefinitionList.Root>
|
|
22
|
+
* ```
|
|
23
|
+
*
|
|
24
|
+
* ## Two defects fixed on the way across
|
|
25
|
+
*
|
|
26
|
+
* **It ignored the app-wide appearance.** The variant defaulted to a literal
|
|
27
|
+
* `"solid"` and never consulted the host's configuration, so a product set to
|
|
28
|
+
* `glass` or `matte` got one panel that stayed solid regardless. Every other
|
|
29
|
+
* component in this package resolves through `useResolvedVariant`; this one
|
|
30
|
+
* predated it. It does now, which means an unset variant follows the app
|
|
31
|
+
* rather than overriding it.
|
|
32
|
+
*
|
|
33
|
+
* **The row separators never rendered.** `dlRecipe` drew them with
|
|
34
|
+
* `& > li:not(:last-child)` — but a `<dl>` contains `<dt>` and `<dd>`, never
|
|
35
|
+
* `<li>`, so the selector matched nothing in the only element the recipe is
|
|
36
|
+
* ever applied to. The rule was present, valid, and dead. It is `& > dd` now,
|
|
37
|
+
* which puts a line after each pair rather than between a term and its own
|
|
38
|
+
* definition.
|
|
39
|
+
*
|
|
40
|
+
* That fix is in the recipe rather than here, so it reaches any consumer using
|
|
41
|
+
* `dlRecipe` directly. Nothing consumed it before this component, so no
|
|
42
|
+
* existing surface changes.
|
|
43
|
+
*
|
|
44
|
+
* ## The `link` / `selected` coercion is gone
|
|
45
|
+
*
|
|
46
|
+
* The originating version silently mapped `link`, `ghost` and `selected` onto
|
|
47
|
+
* `solid`. A coerced variant still renders, so a call site asking for `ghost`
|
|
48
|
+
* saw a solid panel and no warning — the same silent-coercion failure NEH-234
|
|
49
|
+
* documented. `useResolvedVariant`'s allow-list makes the supported set
|
|
50
|
+
* explicit instead: `DL_VARIANTS` is what the recipe actually defines.
|
|
51
|
+
*/
|
|
52
|
+
|
|
53
|
+
const PandaDefinitionList = styled("dl", {
|
|
54
|
+
base: {
|
|
55
|
+
display: "grid",
|
|
56
|
+
gridTemplateColumns: "max-content 1fr",
|
|
57
|
+
gap: "0.5rem 1.5rem",
|
|
58
|
+
padding: "1rem",
|
|
59
|
+
},
|
|
60
|
+
});
|
|
61
|
+
|
|
62
|
+
const PandaTerm = styled("dt", {
|
|
63
|
+
base: {
|
|
64
|
+
fontWeight: "bold",
|
|
65
|
+
gridColumn: 1,
|
|
66
|
+
},
|
|
67
|
+
});
|
|
68
|
+
|
|
69
|
+
const PandaDescription = styled("dd", {
|
|
70
|
+
base: {
|
|
71
|
+
margin: 0,
|
|
72
|
+
gridColumn: 2,
|
|
73
|
+
},
|
|
74
|
+
});
|
|
75
|
+
|
|
76
|
+
/** The appearances `dlRecipe` actually defines. */
|
|
77
|
+
export const DL_VARIANTS = [
|
|
78
|
+
"solid",
|
|
79
|
+
"outline",
|
|
80
|
+
"aurora",
|
|
81
|
+
"glass",
|
|
82
|
+
"matte",
|
|
83
|
+
"none",
|
|
84
|
+
"unstyled",
|
|
85
|
+
] as const;
|
|
86
|
+
|
|
87
|
+
export type DlVariant = (typeof DL_VARIANTS)[number];
|
|
88
|
+
|
|
89
|
+
export type StyledDefinitionListProps = React.PropsWithChildren<
|
|
90
|
+
React.HTMLAttributes<HTMLDListElement> & {
|
|
91
|
+
/**
|
|
92
|
+
* `undefined` is spelled out because the repo runs
|
|
93
|
+
* `exactOptionalPropertyTypes`: without it a caller holding a
|
|
94
|
+
* possibly-unset variant cannot forward it, even though "unset" is
|
|
95
|
+
* precisely the case this component handles by following the app.
|
|
96
|
+
*/
|
|
97
|
+
variant?: AllowedVariant | DlVariant | undefined;
|
|
98
|
+
}
|
|
99
|
+
>;
|
|
100
|
+
|
|
101
|
+
const StyledDefinitionListRoot = React.forwardRef<
|
|
102
|
+
HTMLDListElement,
|
|
103
|
+
StyledDefinitionListProps
|
|
104
|
+
>(({ children, variant, className, ...rest }, ref) => {
|
|
105
|
+
const resolved = useResolvedVariant(variant, DL_VARIANTS);
|
|
106
|
+
|
|
107
|
+
return (
|
|
108
|
+
<PandaDefinitionList
|
|
109
|
+
ref={ref}
|
|
110
|
+
className={[dlRecipe({ variant: resolved }), className]
|
|
111
|
+
.filter(Boolean)
|
|
112
|
+
.join(" ")}
|
|
113
|
+
{...rest}
|
|
114
|
+
>
|
|
115
|
+
{children}
|
|
116
|
+
</PandaDefinitionList>
|
|
117
|
+
);
|
|
118
|
+
});
|
|
119
|
+
|
|
120
|
+
StyledDefinitionListRoot.displayName = "StyledDefinitionList.Root";
|
|
121
|
+
|
|
122
|
+
const StyledDefinitionList = {
|
|
123
|
+
Root: StyledDefinitionListRoot,
|
|
124
|
+
Term: PandaTerm,
|
|
125
|
+
Definition: PandaDescription,
|
|
126
|
+
};
|
|
127
|
+
|
|
128
|
+
/**
|
|
129
|
+
* Re-exported so a consumer can validate a variant before passing it — the
|
|
130
|
+
* same vocabulary `useResolvedVariant` gates on.
|
|
131
|
+
*/
|
|
132
|
+
export { ALL_VARIANTS };
|
|
133
|
+
|
|
134
|
+
export default StyledDefinitionList;
|
|
@@ -0,0 +1,157 @@
|
|
|
1
|
+
"use client";
|
|
2
|
+
|
|
3
|
+
import React from "react";
|
|
4
|
+
import { styled } from "styled-system/jsx";
|
|
5
|
+
import { formRecipe } from "styled-system/recipes";
|
|
6
|
+
import { useResolvedVariant } from "../config/style-config";
|
|
7
|
+
import { log } from "../config/logger";
|
|
8
|
+
import StyledFormLabel from "./StyledFormLabel";
|
|
9
|
+
|
|
10
|
+
/**
|
|
11
|
+
* A group of related form controls, with a visible name.
|
|
12
|
+
*
|
|
13
|
+
* The `<fieldset>`/`<legend>` pair is the only markup that gives a *group* an
|
|
14
|
+
* accessible name. Assistive tech announces the legend when focus enters the
|
|
15
|
+
* group and, for radios in particular, that legend is the question the options
|
|
16
|
+
* are answering — without it a screen reader meets "Yes / No" with no idea what
|
|
17
|
+
* is being asked. That is the reason to reach for this rather than a heading
|
|
18
|
+
* above a `<div>`, which looks identical and carries none of it.
|
|
19
|
+
*
|
|
20
|
+
* ```tsx
|
|
21
|
+
* <StyledFieldset>
|
|
22
|
+
* <StyledFieldset.Legend>Contact preferences</StyledFieldset.Legend>
|
|
23
|
+
* <StyledFieldset.Content>
|
|
24
|
+
* <StyledFieldset.Field>
|
|
25
|
+
* <StyledFieldset.Label htmlFor="email">Email</StyledFieldset.Label>
|
|
26
|
+
* <StyledFieldset.Value><input id="email" /></StyledFieldset.Value>
|
|
27
|
+
* </StyledFieldset.Field>
|
|
28
|
+
* </StyledFieldset.Content>
|
|
29
|
+
* </StyledFieldset>
|
|
30
|
+
* ```
|
|
31
|
+
*
|
|
32
|
+
* ## Two defects fixed on the way across
|
|
33
|
+
*
|
|
34
|
+
* **No variant meant no styling at all.** The root read
|
|
35
|
+
* `variant ? formRecipe({ variant }) : ""` — so a fieldset rendered without an
|
|
36
|
+
* explicit `variant` prop got an empty class string: no surface, no border, no
|
|
37
|
+
* padding, and no response to the app-wide appearance. Every other component in
|
|
38
|
+
* this package treats an absent variant as "follow the app", and 18 HopperGuard
|
|
39
|
+
* call sites were relying on a default that silently did nothing.
|
|
40
|
+
*
|
|
41
|
+
* It resolves through `useResolvedVariant` now, so an unset variant follows the
|
|
42
|
+
* host's configuration and an unrecognised one falls back to `solid` rather
|
|
43
|
+
* than to nothing. **This visibly changes existing fieldsets** — they gain the
|
|
44
|
+
* surface they were always supposed to have, which is why it is called out here
|
|
45
|
+
* rather than buried in the move.
|
|
46
|
+
*
|
|
47
|
+
* **`Label` was a second, divergent form label.** It was a bare `<label>` with
|
|
48
|
+
* `display: block` and a margin — no colour token, no font-size profile, and no
|
|
49
|
+
* `required`/`optional` markers. `StyledFormLabel` in this same package handles
|
|
50
|
+
* all four, and having two labels in one design system is precisely how a
|
|
51
|
+
* product ends up with form rows that do not match each other. `Label` now
|
|
52
|
+
* delegates to it, so a field inside a fieldset and a field outside one are the
|
|
53
|
+
* same control.
|
|
54
|
+
*
|
|
55
|
+
* The DOM shape is unchanged — both render a `<label>` — but the label now
|
|
56
|
+
* follows the user's text-size setting, which it did not before.
|
|
57
|
+
*/
|
|
58
|
+
|
|
59
|
+
const PandaFieldsetLegend = styled("legend", {
|
|
60
|
+
base: { fontWeight: "bold", paddingX: "0.5rem" },
|
|
61
|
+
});
|
|
62
|
+
const PandaFieldsetContent = styled("div", { base: { marginTop: "1rem" } });
|
|
63
|
+
const PandaFieldsetField = styled("div", {
|
|
64
|
+
base: { width: "100%", marginBottom: "1rem" },
|
|
65
|
+
});
|
|
66
|
+
const PandaFieldsetValue = styled("div");
|
|
67
|
+
|
|
68
|
+
/** The appearances `formRecipe` defines. */
|
|
69
|
+
export const FIELDSET_VARIANTS = [
|
|
70
|
+
"solid",
|
|
71
|
+
"outline",
|
|
72
|
+
"lines",
|
|
73
|
+
"aurora",
|
|
74
|
+
"glass",
|
|
75
|
+
"matte",
|
|
76
|
+
"none",
|
|
77
|
+
"unstyled",
|
|
78
|
+
] as const;
|
|
79
|
+
|
|
80
|
+
export type FieldsetVariant = (typeof FIELDSET_VARIANTS)[number];
|
|
81
|
+
|
|
82
|
+
export type StyledFieldsetProps = React.ComponentProps<"fieldset"> & {
|
|
83
|
+
/**
|
|
84
|
+
* `| undefined` is spelled out because the repo runs
|
|
85
|
+
* `exactOptionalPropertyTypes`: without it a caller holding a possibly-unset
|
|
86
|
+
* variant cannot forward it, even though "unset" is exactly the case this
|
|
87
|
+
* component handles by following the app.
|
|
88
|
+
*/
|
|
89
|
+
variant?: FieldsetVariant | undefined;
|
|
90
|
+
};
|
|
91
|
+
|
|
92
|
+
const StyledFieldsetRoot = React.forwardRef<
|
|
93
|
+
HTMLFieldSetElement,
|
|
94
|
+
StyledFieldsetProps
|
|
95
|
+
>(({ children, variant, className, ...props }, ref) => {
|
|
96
|
+
log.trace("StyledFieldset.Root rendered");
|
|
97
|
+
|
|
98
|
+
const resolved = useResolvedVariant(variant, FIELDSET_VARIANTS);
|
|
99
|
+
|
|
100
|
+
return (
|
|
101
|
+
<fieldset
|
|
102
|
+
ref={ref}
|
|
103
|
+
className={[formRecipe({ variant: resolved }), className]
|
|
104
|
+
.filter(Boolean)
|
|
105
|
+
.join(" ")}
|
|
106
|
+
{...props}
|
|
107
|
+
>
|
|
108
|
+
{children}
|
|
109
|
+
</fieldset>
|
|
110
|
+
);
|
|
111
|
+
});
|
|
112
|
+
StyledFieldsetRoot.displayName = "StyledFieldset.Root";
|
|
113
|
+
|
|
114
|
+
const StyledFieldsetLegend = React.forwardRef<
|
|
115
|
+
HTMLLegendElement,
|
|
116
|
+
React.ComponentProps<typeof PandaFieldsetLegend>
|
|
117
|
+
>((props, ref) => <PandaFieldsetLegend ref={ref} {...props} />);
|
|
118
|
+
StyledFieldsetLegend.displayName = "StyledFieldset.Legend";
|
|
119
|
+
|
|
120
|
+
const StyledFieldsetContent = React.forwardRef<
|
|
121
|
+
HTMLDivElement,
|
|
122
|
+
React.ComponentProps<typeof PandaFieldsetContent>
|
|
123
|
+
>((props, ref) => <PandaFieldsetContent ref={ref} {...props} />);
|
|
124
|
+
StyledFieldsetContent.displayName = "StyledFieldset.Content";
|
|
125
|
+
|
|
126
|
+
const StyledFieldsetField = React.forwardRef<
|
|
127
|
+
HTMLDivElement,
|
|
128
|
+
React.ComponentProps<typeof PandaFieldsetField>
|
|
129
|
+
>((props, ref) => <PandaFieldsetField ref={ref} {...props} />);
|
|
130
|
+
StyledFieldsetField.displayName = "StyledFieldset.Field";
|
|
131
|
+
|
|
132
|
+
const StyledFieldsetValue = React.forwardRef<
|
|
133
|
+
HTMLDivElement,
|
|
134
|
+
React.ComponentProps<typeof PandaFieldsetValue>
|
|
135
|
+
>((props, ref) => <PandaFieldsetValue ref={ref} {...props} />);
|
|
136
|
+
StyledFieldsetValue.displayName = "StyledFieldset.Value";
|
|
137
|
+
|
|
138
|
+
interface StyledFieldsetComponentType
|
|
139
|
+
extends React.ForwardRefExoticComponent<
|
|
140
|
+
StyledFieldsetProps & React.RefAttributes<HTMLFieldSetElement>
|
|
141
|
+
> {
|
|
142
|
+
Legend: typeof StyledFieldsetLegend;
|
|
143
|
+
Content: typeof StyledFieldsetContent;
|
|
144
|
+
Field: typeof StyledFieldsetField;
|
|
145
|
+
/** `StyledFormLabel` — the same label used outside a fieldset. */
|
|
146
|
+
Label: typeof StyledFormLabel;
|
|
147
|
+
Value: typeof StyledFieldsetValue;
|
|
148
|
+
}
|
|
149
|
+
|
|
150
|
+
const StyledFieldset = StyledFieldsetRoot as StyledFieldsetComponentType;
|
|
151
|
+
StyledFieldset.Legend = StyledFieldsetLegend;
|
|
152
|
+
StyledFieldset.Content = StyledFieldsetContent;
|
|
153
|
+
StyledFieldset.Field = StyledFieldsetField;
|
|
154
|
+
StyledFieldset.Label = StyledFormLabel;
|
|
155
|
+
StyledFieldset.Value = StyledFieldsetValue;
|
|
156
|
+
|
|
157
|
+
export default StyledFieldset;
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import { styled, type HTMLStyledProps } from "styled-system/jsx";
|
|
2
|
+
|
|
3
|
+
export const StyledFlex = styled("div", {
|
|
4
|
+
base: {
|
|
5
|
+
display: "flex",
|
|
6
|
+
},
|
|
7
|
+
});
|
|
8
|
+
|
|
9
|
+
export type StyledFlexProps = HTMLStyledProps<typeof StyledFlex>;
|
|
10
|
+
|
|
11
|
+
StyledFlex.displayName = "StyledFlex";
|
|
12
|
+
|
|
13
|
+
export default StyledFlex;
|