@spark-ui/components
Version:
Spark (Leboncoin design system) components.
1,772 lines (1,726 loc) • 50 kB
JavaScript
"use strict";
var __defProp = Object.defineProperty;
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
var __getOwnPropNames = Object.getOwnPropertyNames;
var __hasOwnProp = Object.prototype.hasOwnProperty;
var __export = (target, all) => {
for (var name in all)
__defProp(target, name, { get: all[name], enumerable: true });
};
var __copyProps = (to, from, except, desc) => {
if (from && typeof from === "object" || typeof from === "function") {
for (let key of __getOwnPropNames(from))
if (!__hasOwnProp.call(to, key) && key !== except)
__defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
}
return to;
};
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
// src/stepper/index.ts
var stepper_exports = {};
__export(stepper_exports, {
Stepper: () => Stepper2
});
module.exports = __toCommonJS(stepper_exports);
// src/stepper/Stepper.tsx
var import_form_field3 = require("@spark-ui/components/form-field");
var import_react6 = require("react");
// src/input/InputClearButton.tsx
var import_DeleteOutline = require("@spark-ui/icons/DeleteOutline");
var import_class_variance_authority2 = require("class-variance-authority");
// src/icon/Icon.tsx
var import_react2 = require("react");
// src/slot/Slot.tsx
var import_radix_ui = require("radix-ui");
var import_react = require("react");
var import_jsx_runtime = require("react/jsx-runtime");
var Slottable = import_radix_ui.Slot.Slottable;
var Slot = ({ ref, ...props }) => {
return /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_radix_ui.Slot.Root, { ref, ...props });
};
var wrapPolymorphicSlot = (asChild, children, callback) => {
if (!asChild) return callback(children);
return (0, import_react.isValidElement)(children) ? (0, import_react.cloneElement)(
children,
void 0,
callback(children.props.children)
) : null;
};
// src/visually-hidden/VisuallyHidden.tsx
var import_jsx_runtime2 = require("react/jsx-runtime");
var VisuallyHidden = ({ asChild = false, ref, ...props }) => {
const Component = asChild ? Slot : "span";
return /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
Component,
{
...props,
ref,
style: {
// See: https://github.com/twbs/bootstrap/blob/main/scss/mixins/_visually-hidden.scss
position: "absolute",
border: 0,
width: 1,
height: 1,
padding: 0,
margin: -1,
overflow: "hidden",
clip: "rect(0, 0, 0, 0)",
whiteSpace: "nowrap",
wordWrap: "normal",
...props.style
}
}
);
};
VisuallyHidden.displayName = "VisuallyHidden";
// src/icon/Icon.styles.tsx
var import_internal_utils = require("@spark-ui/internal-utils");
var import_class_variance_authority = require("class-variance-authority");
var iconStyles = (0, import_class_variance_authority.cva)(["fill-current shrink-0"], {
variants: {
/**
* Color scheme of the icon.
*/
intent: (0, import_internal_utils.makeVariants)({
current: ["text-current"],
main: ["text-main"],
support: ["text-support"],
accent: ["text-accent"],
basic: ["text-basic"],
success: ["text-success"],
alert: ["text-alert"],
error: ["text-error"],
info: ["text-info"],
neutral: ["text-neutral"]
}),
/**
* Sets the size of the icon.
*/
size: (0, import_internal_utils.makeVariants)({
current: ["u-current-font-size"],
sm: ["w-sz-16", "h-sz-16"],
md: ["w-sz-24", "h-sz-24"],
lg: ["w-sz-32", "h-sz-32"],
xl: ["w-sz-40", "h-sz-40"]
})
}
});
// src/icon/Icon.tsx
var import_jsx_runtime3 = require("react/jsx-runtime");
var Icon = ({
label,
className,
size = "current",
intent = "current",
children,
...others
}) => {
const child = import_react2.Children.only(children);
return /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)(import_jsx_runtime3.Fragment, { children: [
(0, import_react2.cloneElement)(child, {
className: iconStyles({ className, size, intent }),
"data-spark-component": "icon",
"aria-hidden": "true",
focusable: "false",
...others
}),
label && /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(VisuallyHidden, { children: label })
] });
};
Icon.displayName = "Icon";
// src/input/InputGroupContext.ts
var import_react3 = require("react");
var InputGroupContext = (0, import_react3.createContext)(null);
var useInputGroup = () => {
const context = (0, import_react3.useContext)(InputGroupContext);
return context || { isStandalone: true };
};
// src/input/InputClearButton.tsx
var import_jsx_runtime4 = require("react/jsx-runtime");
var Root = ({ className, tabIndex = -1, onClick, ref, ...others }) => {
const { onClear, hasTrailingIcon } = useInputGroup();
const handleClick = (event) => {
if (onClick) {
onClick(event);
}
if (onClear) {
onClear();
}
};
return /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(
"button",
{
ref,
className: (0, import_class_variance_authority2.cx)(
className,
"pointer-events-auto absolute top-1/2 -translate-y-1/2",
"inline-flex h-full items-center justify-center outline-hidden",
"text-neutral hover:text-neutral-hovered",
hasTrailingIcon ? "right-3xl px-sz-12" : "pl-md pr-lg right-0"
),
tabIndex,
onClick: handleClick,
type: "button",
...others,
children: /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(Icon, { size: "sm", children: /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(import_DeleteOutline.DeleteOutline, {}) })
}
);
};
var InputClearButton = Object.assign(Root, {
id: "ClearButton"
});
Root.displayName = "InputGroup.ClearButton";
// src/input/InputGroup.tsx
var import_form_field = require("@spark-ui/components/form-field");
var import_use_combined_state = require("@spark-ui/hooks/use-combined-state");
var import_use_merge_refs = require("@spark-ui/hooks/use-merge-refs");
var import_react4 = require("react");
// src/input/InputGroup.styles.ts
var import_class_variance_authority3 = require("class-variance-authority");
var inputGroupStyles = (0, import_class_variance_authority3.cva)(["relative inline-flex w-full"], {
variants: {
/**
* When `true`, prevents the user from interacting.
*/
disabled: {
true: [
"cursor-not-allowed",
"relative",
"after:absolute",
"after:top-0",
"after:h-full",
"after:w-full",
"after:border-sm after:border-outline",
"after:rounded-lg"
],
false: "after:hidden"
},
/**
* Sets the component as interactive or not.
*/
readOnly: {
true: [
"relative",
"after:absolute",
"after:top-0",
"after:h-full",
"after:w-full",
"after:border-sm after:border-outline",
"after:rounded-lg"
],
false: "after:hidden"
}
}
});
// src/input/InputGroup.tsx
var import_jsx_runtime5 = require("react/jsx-runtime");
var InputGroup = ({
className,
children: childrenProp,
state: stateProp,
disabled: disabledProp,
readOnly: readOnlyProp,
onClear,
ref: forwardedRef,
...others
}) => {
const getElementId = (element) => {
return element ? element.type.id : "";
};
const findElement = (...values) => {
return children.find((child) => values.includes(getElementId(child) || ""));
};
const children = import_react4.Children.toArray(childrenProp).filter(import_react4.isValidElement);
const input = findElement("Input");
const props = input?.props || {};
const inputRef = (0, import_react4.useRef)(null);
const onClearRef = (0, import_react4.useRef)(onClear);
const ref = (0, import_use_merge_refs.useMergeRefs)(input?.ref, inputRef);
const [value, onChange] = (0, import_use_combined_state.useCombinedState)(
props.value,
props.defaultValue,
props.onValueChange
);
const field = (0, import_form_field.useFormFieldControl)();
const state = field.state ?? stateProp;
const disabled = field.disabled || !!disabledProp;
const readOnly = field.readOnly || !!readOnlyProp;
const leadingAddon = findElement("LeadingAddon");
const leadingIcon = findElement("LeadingIcon");
const clearButton = findElement("ClearButton");
const trailingIcon = findElement("TrailingIcon");
const trailingAddon = findElement("TrailingAddon");
const hasLeadingAddon = !!leadingAddon;
const hasTrailingAddon = !!trailingAddon;
const hasLeadingIcon = !!leadingIcon;
const hasTrailingIcon = !!trailingIcon;
const hasClearButton = !!value && !!clearButton && !disabled && !readOnly;
const handleChange = (event) => {
if (props.onChange) {
props.onChange(event);
}
onChange(event.target.value);
};
const handleClear = (0, import_react4.useCallback)(() => {
if (onClearRef.current) {
onClearRef.current();
}
onChange("");
inputRef.current.focus();
}, [onChange]);
const current = (0, import_react4.useMemo)(() => {
return {
state,
disabled,
readOnly,
hasLeadingIcon,
hasTrailingIcon,
hasLeadingAddon,
hasTrailingAddon,
hasClearButton,
onClear: handleClear
};
}, [
state,
disabled,
readOnly,
hasLeadingIcon,
hasTrailingIcon,
hasLeadingAddon,
hasTrailingAddon,
hasClearButton,
handleClear
]);
(0, import_react4.useEffect)(() => {
onClearRef.current = onClear;
}, [onClear]);
return /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(InputGroupContext.Provider, { value: current, children: /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)(
"div",
{
ref: forwardedRef,
className: inputGroupStyles({ disabled, readOnly, className }),
...others,
children: [
hasLeadingAddon && leadingAddon,
/* @__PURE__ */ (0, import_jsx_runtime5.jsxs)("div", { className: "relative inline-flex w-full", children: [
input && (0, import_react4.cloneElement)(input, {
ref,
defaultValue: void 0,
value: value ?? "",
onChange: handleChange
}),
leadingIcon,
hasClearButton && clearButton,
trailingIcon
] }),
hasTrailingAddon && trailingAddon
]
}
) });
};
InputGroup.displayName = "InputGroup";
// src/input/InputLeadingAddon.tsx
var import_class_variance_authority5 = require("class-variance-authority");
// src/input/InputAddon.tsx
var import_react5 = require("react");
// src/input/InputAddon.styles.ts
var import_class_variance_authority4 = require("class-variance-authority");
var inputAddonStyles = (0, import_class_variance_authority4.cva)(
[
"overflow-hidden",
"border-sm",
"shrink-0",
"h-full",
"focus-visible:relative focus-visible:z-raised"
],
{
variants: {
/**
* Change the component to the HTML tag or custom component of the only child.
*/
asChild: { false: ["flex", "items-center", "px-lg"] },
intent: {
neutral: "border-outline",
error: "border-error",
alert: "border-alert",
success: "border-success"
},
/**
* Disable the input addon, preventing user interaction and adding opacity.
*/
disabled: {
true: ["pointer-events-none border-outline!"]
},
/**
* Changes input addon styles based on the read only status from the input.
*/
readOnly: {
true: ["pointer-events-none"]
},
/**
* Main style of the input addon.
*/
design: {
text: "",
solid: "",
inline: ""
}
},
compoundVariants: [
{
disabled: false,
readOnly: false,
design: "text",
class: ["bg-surface", "text-on-surface"]
},
{
disabled: true,
design: "text",
class: ["text-on-surface/dim-3"]
},
{
disabled: true,
design: ["solid", "inline"],
class: ["opacity-dim-3"]
}
],
defaultVariants: {
intent: "neutral"
}
}
);
// src/input/InputAddon.tsx
var import_jsx_runtime6 = require("react/jsx-runtime");
var InputAddon = ({
asChild: asChildProp,
className,
children,
ref,
...others
}) => {
const { state, disabled, readOnly } = useInputGroup();
const isRawText = typeof children === "string";
const asChild = !!(isRawText ? false : asChildProp);
const child = isRawText ? children : import_react5.Children.only(children);
const Component = asChild && !isRawText ? Slot : "div";
const getDesign = () => {
if (isRawText) return "text";
return asChild ? "solid" : "inline";
};
const design = getDesign();
return /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(
Component,
{
ref,
className: inputAddonStyles({
className,
intent: state,
disabled,
readOnly,
asChild,
design
}),
...disabled && { tabIndex: -1 },
...others,
children: child
}
);
};
InputAddon.displayName = "InputGroup.Addon";
// src/input/InputLeadingAddon.tsx
var import_jsx_runtime7 = require("react/jsx-runtime");
var Root2 = ({ className, ref, ...others }) => {
const { disabled, readOnly } = useInputGroup();
const isInactive = disabled || readOnly;
return /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("div", { className: (0, import_class_variance_authority5.cx)("rounded-l-lg", isInactive ? "bg-on-surface/dim-5" : null), children: /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(
InputAddon,
{
ref,
className: (0, import_class_variance_authority5.cx)(className, "rounded-r-0! mr-[-1px] rounded-l-lg"),
...others
}
) });
};
var InputLeadingAddon = Object.assign(Root2, {
id: "LeadingAddon"
});
Root2.displayName = "InputGroup.LeadingAddon";
// src/input/InputLeadingIcon.tsx
var import_class_variance_authority7 = require("class-variance-authority");
// src/input/InputIcon.tsx
var import_class_variance_authority6 = require("class-variance-authority");
var import_jsx_runtime8 = require("react/jsx-runtime");
var InputIcon = ({ className, intent, children, ...others }) => {
const { disabled, readOnly } = useInputGroup();
const isInactive = disabled || readOnly;
return /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(
Icon,
{
intent,
className: (0, import_class_variance_authority6.cx)(
className,
"pointer-events-none absolute top-[calc(var(--spacing-sz-44)/2)] -translate-y-1/2",
intent ? void 0 : "text-neutral peer-focus:text-outline-high",
isInactive ? "opacity-dim-3" : void 0
),
...others,
children
}
);
};
InputIcon.displayName = "InputGroup.Icon";
// src/input/InputLeadingIcon.tsx
var import_jsx_runtime9 = require("react/jsx-runtime");
var InputLeadingIcon = ({ className, ...others }) => /* @__PURE__ */ (0, import_jsx_runtime9.jsx)(InputIcon, { className: (0, import_class_variance_authority7.cx)(className, "left-lg text-body-1"), ...others });
InputLeadingIcon.id = "LeadingIcon";
InputLeadingIcon.displayName = "InputGroup.LeadingIcon";
// src/input/InputTrailingAddon.tsx
var import_class_variance_authority8 = require("class-variance-authority");
var import_jsx_runtime10 = require("react/jsx-runtime");
var Root3 = ({ className, ref, ...others }) => {
const { disabled, readOnly } = useInputGroup();
const isInactive = disabled || readOnly;
return /* @__PURE__ */ (0, import_jsx_runtime10.jsx)("div", { className: (0, import_class_variance_authority8.cx)("rounded-r-lg", isInactive ? "bg-on-surface/dim-5" : null), children: /* @__PURE__ */ (0, import_jsx_runtime10.jsx)(
InputAddon,
{
ref,
className: (0, import_class_variance_authority8.cx)(className, "rounded-l-0! ml-[-1px] rounded-r-lg"),
...others
}
) });
};
var InputTrailingAddon = Object.assign(Root3, {
id: "TrailingAddon"
});
Root3.displayName = "InputGroup.TrailingAddon";
// src/input/InputTrailingIcon.tsx
var import_class_variance_authority9 = require("class-variance-authority");
var import_jsx_runtime11 = require("react/jsx-runtime");
var InputTrailingIcon = ({ className, ...others }) => /* @__PURE__ */ (0, import_jsx_runtime11.jsx)(InputIcon, { className: (0, import_class_variance_authority9.cx)(className, "right-lg text-body-1"), ...others });
InputTrailingIcon.id = "TrailingIcon";
InputTrailingIcon.displayName = "InputGroup.TrailingIcon";
// src/input/Input.tsx
var import_form_field2 = require("@spark-ui/components/form-field");
// src/input/Input.styles.ts
var import_class_variance_authority10 = require("class-variance-authority");
var inputStyles = (0, import_class_variance_authority10.cva)(
[
"relative",
"border-sm",
"peer",
"w-full",
"appearance-none outline-hidden",
"bg-surface",
"text-ellipsis text-body-1 text-on-surface",
"caret-neutral",
"autofill:shadow-surface autofill:shadow-[inset_0_0_0px_1000px]",
"disabled:cursor-not-allowed disabled:border-outline disabled:bg-on-surface/dim-5 disabled:text-on-surface/dim-3",
"read-only:cursor-default read-only:pointer-events-none read-only:bg-on-surface/dim-5",
"focus:ring-1 focus:ring-inset"
],
{
variants: {
/**
* Change the component to the HTML tag or custom component of the only child.
*/
asChild: {
true: ["min-h-sz-44"],
false: ["h-sz-44"]
},
/**
* Color scheme of the button.
*/
intent: {
neutral: [
"border-outline",
"hover:border-outline-high",
"focus:ring-outline-high focus:border-outline-high"
],
success: ["border-success", "focus:ring-success"],
alert: ["border-alert", "focus:ring-alert"],
error: ["border-error", "focus:ring-error"]
},
/**
* Sets if there is an addon before the input text.
*/
hasLeadingAddon: {
true: ["rounded-l-0"],
false: ["rounded-l-lg"]
},
/**
* Sets if there is an addon after the input text.
*/
hasTrailingAddon: {
true: ["rounded-r-0"],
false: ["rounded-r-lg"]
},
/**
* Sets if there is an icon before the input text.
*/
hasLeadingIcon: {
true: ["pl-3xl"],
false: ["pl-lg"]
},
/**
* Sets if there is an icon after the input text.
*/
hasTrailingIcon: { true: "" },
/**
* Sets if there is a button to clear the input text.
*/
hasClearButton: { true: "" }
},
compoundVariants: [
{
hasTrailingIcon: false,
hasClearButton: false,
class: "pr-lg"
},
{
hasTrailingIcon: true,
hasClearButton: false,
class: "pr-3xl"
},
{
hasTrailingIcon: false,
hasClearButton: true,
class: "pr-3xl"
},
{
hasTrailingIcon: true,
hasClearButton: true,
class: "pr-[calc(var(--spacing-3xl)*2)]"
}
],
defaultVariants: {
intent: "neutral"
}
}
);
// src/input/Input.tsx
var import_jsx_runtime12 = require("react/jsx-runtime");
var Root4 = ({
className,
asChild = false,
onValueChange,
onChange,
onKeyDown,
disabled: disabledProp,
readOnly: readOnlyProp,
ref,
...others
}) => {
const field = (0, import_form_field2.useFormFieldControl)();
const group = useInputGroup();
const { id, name, isInvalid, isRequired, description } = field;
const {
hasLeadingAddon,
hasTrailingAddon,
hasLeadingIcon,
hasTrailingIcon,
hasClearButton,
onClear
} = group;
const Component = asChild ? Slot : "input";
const state = field.state || group.state;
const disabled = field.disabled || group.disabled || disabledProp;
const readOnly = field.readOnly || group.readOnly || readOnlyProp;
const handleChange = (event) => {
if (onChange) {
onChange(event);
}
if (onValueChange) {
onValueChange(event.target.value);
}
};
const handleKeyDown = (event) => {
if (onKeyDown) {
onKeyDown(event);
}
if (hasClearButton && onClear && event.key === "Escape") {
onClear();
}
};
return /* @__PURE__ */ (0, import_jsx_runtime12.jsx)(
Component,
{
ref,
id,
name,
className: inputStyles({
asChild,
className,
intent: state,
hasLeadingAddon: !!hasLeadingAddon,
hasTrailingAddon: !!hasTrailingAddon,
hasLeadingIcon: !!hasLeadingIcon,
hasTrailingIcon: !!hasTrailingIcon,
hasClearButton: !!hasClearButton
}),
disabled,
readOnly,
required: isRequired,
"aria-describedby": description,
"aria-invalid": isInvalid,
onChange: handleChange,
onKeyDown: handleKeyDown,
...others
}
);
};
var Input = Object.assign(Root4, {
id: "Input"
});
Root4.displayName = "Input";
// src/input/index.ts
var InputGroup2 = Object.assign(InputGroup, {
LeadingAddon: InputLeadingAddon,
TrailingAddon: InputTrailingAddon,
LeadingIcon: InputLeadingIcon,
TrailingIcon: InputTrailingIcon,
ClearButton: InputClearButton
});
InputGroup2.displayName = "InputGroup";
InputLeadingAddon.displayName = "InputGroup.LeadingAddon";
InputTrailingAddon.displayName = "InputGroup.TrailingAddon";
InputLeadingIcon.displayName = "InputGroup.LeadingIcon";
InputTrailingIcon.displayName = "InputGroup.TrailingIcon";
InputClearButton.displayName = "InputGroup.ClearButton";
// src/stepper/useStepper.ts
var import_numberfield = require("@react-aria/numberfield");
var import_numberfield2 = require("@react-stately/numberfield");
var useStepper = ({
inputRef,
locale = "fr",
...rest
}) => {
const state = (0, import_numberfield2.useNumberFieldState)({
...rest,
isDisabled: rest.disabled,
isReadOnly: rest.readOnly,
isRequired: rest.required,
locale
});
const { groupProps, inputProps, incrementButtonProps, decrementButtonProps } = (0, import_numberfield.useNumberField)(
{
isWheelDisabled: false,
...rest,
isDisabled: rest.disabled,
isReadOnly: rest.readOnly,
isRequired: rest.required
},
state,
inputRef
);
return {
groupProps,
inputProps,
incrementButtonProps,
decrementButtonProps
};
};
// src/stepper/Stepper.tsx
var import_jsx_runtime13 = require("react/jsx-runtime");
var StepperContext = (0, import_react6.createContext)(null);
var Stepper = ({
children,
formatOptions,
minValue,
maxValue,
incrementAriaLabel,
decrementAriaLabel,
ref: forwardedRef,
...stepperProps
}) => {
const inputRef = (0, import_react6.useRef)(null);
const {
groupProps,
inputProps: _inputProps,
incrementButtonProps: _incrementButtonProps,
decrementButtonProps: _decrementButtonProps
} = useStepper({
...{
...stepperProps,
onChange: stepperProps.onValueChange
},
formatOptions,
minValue,
maxValue,
incrementAriaLabel,
decrementAriaLabel,
inputRef
});
const formFieldControlProps = (0, import_form_field3.useFormFieldControl)();
const isWrappedInFormField = !!formFieldControlProps.id;
const incrementButtonProps = {
..._incrementButtonProps,
...isWrappedInFormField && { "aria-controls": formFieldControlProps.id }
};
const decrementButtonProps = {
..._decrementButtonProps,
...isWrappedInFormField && { "aria-controls": formFieldControlProps.id }
};
const inputProps = {
..._inputProps,
...isWrappedInFormField && {
id: formFieldControlProps.id,
required: formFieldControlProps.isRequired,
"aria-invalid": formFieldControlProps.isInvalid ? true : void 0
}
};
const { onValueChange: _, ...remainingStepperProps } = stepperProps;
return /* @__PURE__ */ (0, import_jsx_runtime13.jsx)(
StepperContext.Provider,
{
value: { incrementButtonProps, decrementButtonProps, inputProps, inputRef },
children: /* @__PURE__ */ (0, import_jsx_runtime13.jsx)(
InputGroup2,
{
...remainingStepperProps,
...groupProps,
"data-spark-component": "stepper",
ref: forwardedRef,
children
}
)
}
);
};
Stepper.displayName = "Stepper";
var useStepperContext = () => {
const context = (0, import_react6.useContext)(StepperContext);
if (!context) {
throw Error("useStepperContext must be used within a Stepper provider");
}
return context;
};
// src/stepper/StepperButton.tsx
var import_button2 = require("@react-aria/button");
var import_Minus = require("@spark-ui/icons/Minus");
var import_Plus = require("@spark-ui/icons/Plus");
var import_react8 = require("react");
// src/button/Button.tsx
var import_class_variance_authority13 = require("class-variance-authority");
var import_react7 = require("react");
// src/spinner/Spinner.styles.tsx
var import_internal_utils2 = require("@spark-ui/internal-utils");
var import_class_variance_authority11 = require("class-variance-authority");
var defaultVariants = {
intent: "current",
size: "current",
isBackgroundVisible: false
};
var spinnerStyles = (0, import_class_variance_authority11.cva)(
["inline-block", "border-solid", "rounded-full", "border-md", "animate-spin"],
{
variants: {
/**
* Use `size` prop to set the size of the spinner. If you want to set the full size for the spinner, don't forget to add a wrapping container with its own size.
*/
size: {
current: ["u-current-font-size"],
sm: ["w-sz-20", "h-sz-20"],
md: ["w-sz-28", "h-sz-28"],
full: ["w-full", "h-full"]
},
/**
* Color scheme of the spinner.
*/
intent: (0, import_internal_utils2.makeVariants)({
current: ["border-current"],
main: ["border-main"],
support: ["border-support"],
accent: ["border-accent"],
basic: ["border-basic"],
success: ["border-success"],
alert: ["border-alert"],
error: ["border-error"],
info: ["border-info"],
neutral: ["border-neutral"]
}),
/**
* Size of the button.
*/
isBackgroundVisible: {
true: ["border-b-neutral-container", "border-l-neutral-container"],
false: ["border-b-transparent", "border-l-transparent"]
}
},
defaultVariants
}
);
// src/spinner/Spinner.tsx
var import_jsx_runtime14 = require("react/jsx-runtime");
var Spinner = ({
className,
size = "current",
intent = "current",
label,
isBackgroundVisible,
ref,
...others
}) => {
return /* @__PURE__ */ (0, import_jsx_runtime14.jsx)(
"span",
{
role: "status",
"data-spark-component": "spinner",
ref,
className: spinnerStyles({ className, size, intent, isBackgroundVisible }),
...others,
children: label && /* @__PURE__ */ (0, import_jsx_runtime14.jsx)(VisuallyHidden, { children: label })
}
);
};
// src/button/Button.styles.tsx
var import_internal_utils8 = require("@spark-ui/internal-utils");
var import_class_variance_authority12 = require("class-variance-authority");
// src/button/variants/filled.ts
var import_internal_utils3 = require("@spark-ui/internal-utils");
var filledVariants = [
// Main
{
intent: "main",
design: "filled",
class: (0, import_internal_utils3.tw)([
"bg-main",
"text-on-main",
"hover:bg-main-hovered",
"enabled:active:bg-main-hovered",
"focus-visible:bg-main-hovered"
])
},
// Support
{
intent: "support",
design: "filled",
class: (0, import_internal_utils3.tw)([
"bg-support",
"text-on-support",
"hover:bg-support-hovered",
"enabled:active:bg-support-hovered",
"focus-visible:bg-support-hovered"
])
},
// Accent
{
intent: "accent",
design: "filled",
class: (0, import_internal_utils3.tw)([
"bg-accent",
"text-on-accent",
"hover:bg-accent-hovered",
"enabled:active:bg-accent-hovered",
"focus-visible:bg-accent-hovered"
])
},
// Basic
{
intent: "basic",
design: "filled",
class: (0, import_internal_utils3.tw)([
"bg-basic",
"text-on-basic",
"hover:bg-basic-hovered",
"enabled:active:bg-basic-hovered",
"focus-visible:bg-basic-hovered"
])
},
// Success
{
intent: "success",
design: "filled",
class: (0, import_internal_utils3.tw)([
"bg-success",
"text-on-success",
"hover:bg-success-hovered",
"enabled:active:bg-success-hovered",
"focus-visible:bg-success-hovered"
])
},
// Alert
{
intent: "alert",
design: "filled",
class: (0, import_internal_utils3.tw)([
"bg-alert",
"text-on-alert",
"hover:bg-alert-hovered",
"enabled:active:bg-alert-hovered",
"focus-visible:bg-alert-hovered"
])
},
// Danger
{
intent: "danger",
design: "filled",
class: (0, import_internal_utils3.tw)([
"text-on-error bg-error",
"hover:bg-error-hovered enabled:active:bg-error-hovered",
"focus-visible:bg-error-hovered"
])
},
// Info
{
intent: "info",
design: "filled",
class: (0, import_internal_utils3.tw)([
"text-on-error bg-info",
"hover:bg-info-hovered enabled:active:bg-info-hovered",
"focus-visible:bg-info-hovered"
])
},
// Neutral
{
intent: "neutral",
design: "filled",
class: (0, import_internal_utils3.tw)([
"bg-neutral",
"text-on-neutral",
"hover:bg-neutral-hovered",
"enabled:active:bg-neutral-hovered",
"focus-visible:bg-neutral-hovered"
])
},
// Surface
{
intent: "surface",
design: "filled",
class: (0, import_internal_utils3.tw)([
"bg-surface",
"text-on-surface",
"hover:bg-surface-hovered",
"enabled:active:bg-surface-hovered",
"focus-visible:bg-surface-hovered"
])
}
];
// src/button/variants/ghost.ts
var import_internal_utils4 = require("@spark-ui/internal-utils");
var ghostVariants = [
{
intent: "main",
design: "ghost",
class: (0, import_internal_utils4.tw)([
"text-main",
"hover:bg-main/dim-5",
"enabled:active:bg-main/dim-5",
"focus-visible:bg-main/dim-5"
])
},
{
intent: "support",
design: "ghost",
class: (0, import_internal_utils4.tw)([
"text-support",
"hover:bg-support/dim-5",
"enabled:active:bg-support/dim-5",
"focus-visible:bg-support/dim-5"
])
},
{
intent: "accent",
design: "ghost",
class: (0, import_internal_utils4.tw)([
"text-accent",
"hover:bg-accent/dim-5",
"enabled:active:bg-accent/dim-5",
"focus-visible:bg-accent/dim-5"
])
},
{
intent: "basic",
design: "ghost",
class: (0, import_internal_utils4.tw)([
"text-basic",
"hover:bg-basic/dim-5",
"enabled:active:bg-basic/dim-5",
"focus-visible:bg-basic/dim-5"
])
},
{
intent: "success",
design: "ghost",
class: (0, import_internal_utils4.tw)([
"text-success",
"hover:bg-success/dim-5",
"enabled:active:bg-success/dim-5",
"focus-visible:bg-success/dim-5"
])
},
{
intent: "alert",
design: "ghost",
class: (0, import_internal_utils4.tw)([
"text-alert",
"hover:bg-alert/dim-5",
"enabled:active:bg-alert/dim-5",
"focus-visible:bg-alert/dim-5"
])
},
{
intent: "danger",
design: "ghost",
class: (0, import_internal_utils4.tw)([
"text-error",
"hover:bg-error/dim-5",
"enabled:active:bg-error/dim-5",
"focus-visible:bg-error/dim-5"
])
},
{
intent: "info",
design: "ghost",
class: (0, import_internal_utils4.tw)([
"text-info",
"hover:bg-info/dim-5",
"enabled:active:bg-info/dim-5",
"focus-visible:bg-info/dim-5"
])
},
{
intent: "neutral",
design: "ghost",
class: (0, import_internal_utils4.tw)([
"text-neutral",
"hover:bg-neutral/dim-5",
"enabled:active:bg-neutral/dim-5",
"focus-visible:bg-neutral/dim-5"
])
},
{
intent: "surface",
design: "ghost",
class: (0, import_internal_utils4.tw)([
"text-surface",
"hover:bg-surface/dim-5",
"enabled:active:bg-surface/dim-5",
"focus-visible:bg-surface/dim-5"
])
}
];
// src/button/variants/outlined.ts
var import_internal_utils5 = require("@spark-ui/internal-utils");
var outlinedVariants = [
{
intent: "main",
design: "outlined",
class: (0, import_internal_utils5.tw)([
"hover:bg-main/dim-5",
"enabled:active:bg-main/dim-5",
"focus-visible:bg-main/dim-5",
"text-main"
])
},
{
intent: "support",
design: "outlined",
class: (0, import_internal_utils5.tw)([
"hover:bg-support/dim-5",
"enabled:active:bg-support/dim-5",
"focus-visible:bg-support/dim-5",
"text-support"
])
},
{
intent: "accent",
design: "outlined",
class: (0, import_internal_utils5.tw)([
"hover:bg-accent/dim-5",
"enabled:active:bg-accent/dim-5",
"focus-visible:bg-accent/dim-5",
"text-accent"
])
},
{
intent: "basic",
design: "outlined",
class: (0, import_internal_utils5.tw)([
"hover:bg-basic/dim-5",
"enabled:active:bg-basic/dim-5",
"focus-visible:bg-basic/dim-5",
"text-basic"
])
},
{
intent: "success",
design: "outlined",
class: (0, import_internal_utils5.tw)([
"hover:bg-success/dim-5",
"enabled:active:bg-success/dim-5",
"focus-visible:bg-success/dim-5",
"text-success"
])
},
{
intent: "alert",
design: "outlined",
class: (0, import_internal_utils5.tw)([
"hover:bg-alert/dim-5",
"enabled:active:bg-alert/dim-5",
"focus-visible:bg-alert/dim-5",
"text-alert"
])
},
{
intent: "danger",
design: "outlined",
class: (0, import_internal_utils5.tw)([
"hover:bg-error/dim-5",
"enabled:active:bg-error/dim-5",
"focus-visible:bg-error/dim-5",
"text-error"
])
},
{
intent: "info",
design: "outlined",
class: (0, import_internal_utils5.tw)([
"hover:bg-info/dim-5",
"enabled:active:bg-info/dim-5",
"focus-visible:bg-info/dim-5",
"text-info"
])
},
{
intent: "neutral",
design: "outlined",
class: (0, import_internal_utils5.tw)([
"hover:bg-neutral/dim-5",
"enabled:active:bg-neutral/dim-5",
"focus-visible:bg-neutral/dim-5",
"text-neutral"
])
},
{
intent: "surface",
design: "outlined",
class: (0, import_internal_utils5.tw)([
"hover:bg-surface/dim-5",
"enabled:active:bg-surface/dim-5",
"focus-visible:bg-surface/dim-5",
"text-surface"
])
}
];
// src/button/variants/tinted.ts
var import_internal_utils6 = require("@spark-ui/internal-utils");
var tintedVariants = [
{
intent: "main",
design: "tinted",
class: (0, import_internal_utils6.tw)([
"bg-main-container",
"text-on-main-container",
"hover:bg-main-container-hovered",
"enabled:active:bg-main-container-hovered",
"focus-visible:bg-main-container-hovered"
])
},
{
intent: "support",
design: "tinted",
class: (0, import_internal_utils6.tw)([
"bg-support-container",
"text-on-support-container",
"hover:bg-support-container-hovered",
"enabled:active:bg-support-container-hovered",
"focus-visible:bg-support-container-hovered"
])
},
{
intent: "accent",
design: "tinted",
class: (0, import_internal_utils6.tw)([
"bg-accent-container",
"text-on-accent-container",
"hover:bg-accent-container-hovered",
"enabled:active:bg-accent-container-hovered",
"focus-visible:bg-accent-container-hovered"
])
},
{
intent: "basic",
design: "tinted",
class: (0, import_internal_utils6.tw)([
"bg-basic-container",
"text-on-basic-container",
"hover:bg-basic-container-hovered",
"enabled:active:bg-basic-container-hovered",
"focus-visible:bg-basic-container-hovered"
])
},
{
intent: "success",
design: "tinted",
class: (0, import_internal_utils6.tw)([
"bg-success-container",
"text-on-success-container",
"hover:bg-success-container-hovered",
"enabled:active:bg-success-container-hovered",
"focus-visible:bg-success-container-hovered"
])
},
{
intent: "alert",
design: "tinted",
class: (0, import_internal_utils6.tw)([
"bg-alert-container",
"text-on-alert-container",
"hover:bg-alert-container-hovered",
"enabled:active:bg-alert-container-hovered",
"focus-visible:bg-alert-container-hovered"
])
},
{
intent: "danger",
design: "tinted",
class: (0, import_internal_utils6.tw)([
"bg-error-container",
"text-on-error-container",
"hover:bg-error-container-hovered",
"enabled:active:bg-error-container-hovered",
"focus-visible:bg-error-container-hovered"
])
},
{
intent: "info",
design: "tinted",
class: (0, import_internal_utils6.tw)([
"bg-info-container",
"text-on-info-container",
"hover:bg-info-container-hovered",
"enabled:active:bg-info-container-hovered",
"focus-visible:bg-info-container-hovered"
])
},
{
intent: "neutral",
design: "tinted",
class: (0, import_internal_utils6.tw)([
"bg-neutral-container",
"text-on-neutral-container",
"hover:bg-neutral-container-hovered",
"enabled:active:bg-neutral-container-hovered",
"focus-visible:bg-neutral-container-hovered"
])
},
{
intent: "surface",
design: "tinted",
class: (0, import_internal_utils6.tw)([
"bg-surface",
"text-on-surface",
"hover:bg-surface-hovered",
"enabled:active:bg-surface-hovered",
"focus-visible:bg-surface-hovered"
])
}
];
// src/button/variants/contrast.ts
var import_internal_utils7 = require("@spark-ui/internal-utils");
var contrastVariants = [
{
intent: "main",
design: "contrast",
class: (0, import_internal_utils7.tw)([
"text-main",
"hover:bg-main-container-hovered",
"enabled:active:bg-main-container-hovered",
"focus-visible:bg-main-container-hovered"
])
},
{
intent: "support",
design: "contrast",
class: (0, import_internal_utils7.tw)([
"text-support",
"hover:bg-support-container-hovered",
"enabled:active:bg-support-container-hovered",
"focus-visible:bg-support-container-hovered"
])
},
{
intent: "accent",
design: "contrast",
class: (0, import_internal_utils7.tw)([
"text-accent",
"hover:bg-accent-container-hovered",
"enabled:active:bg-accent-container-hovered",
"focus-visible:bg-accent-container-hovered"
])
},
{
intent: "basic",
design: "contrast",
class: (0, import_internal_utils7.tw)([
"text-basic",
"hover:bg-basic-container-hovered",
"enabled:active:bg-basic-container-hovered",
"focus-visible:bg-basic-container-hovered"
])
},
{
intent: "success",
design: "contrast",
class: (0, import_internal_utils7.tw)([
"text-success",
"hover:bg-success-container-hovered",
"enabled:active:bg-success-container-hovered",
"focus-visible:bg-success-container-hovered"
])
},
{
intent: "alert",
design: "contrast",
class: (0, import_internal_utils7.tw)([
"text-alert",
"hover:bg-alert-container-hovered",
"enabled:active:bg-alert-container-hovered",
"focus-visible:bg-alert-container-hovered"
])
},
{
intent: "danger",
design: "contrast",
class: (0, import_internal_utils7.tw)([
"text-error",
"hover:bg-error-container-hovered",
"enabled:active:bg-error-container-hovered",
"focus-visible:bg-error-container-hovered"
])
},
{
intent: "info",
design: "contrast",
class: (0, import_internal_utils7.tw)([
"text-info",
"hover:bg-info-container-hovered",
"enabled:active:bg-info-container-hovered",
"focus-visible:bg-info-container-hovered"
])
},
{
intent: "neutral",
design: "contrast",
class: (0, import_internal_utils7.tw)([
"text-neutral",
"hover:bg-neutral-container-hovered",
"enabled:active:bg-neutral-container-hovered",
"focus-visible:bg-neutral-container-hovered"
])
},
{
intent: "surface",
design: "contrast",
class: (0, import_internal_utils7.tw)([
"text-on-surface",
"hover:bg-surface-hovered",
"enabled:active:bg-surface-hovered",
"focus-visible:bg-surface-hovered"
])
}
];
// src/button/Button.styles.tsx
var buttonStyles = (0, import_class_variance_authority12.cva)(
[
"u-shadow-border-transition",
"box-border inline-flex items-center justify-center gap-md whitespace-nowrap",
"px-lg",
"text-body-1 font-bold",
"focus-visible:u-outline"
],
{
variants: {
/**
* Main style of the button.
*
* - `filled`: Button will be plain.
*
* - `outlined`: Button will be transparent with an outline.
*
* - `tinted`: Button will be filled but using a lighter color scheme.
*
* - `ghost`: Button will look like a link. No borders, plain text.
*
* - `contrast`: Button will be surface filled. No borders, plain text.
*
*/
design: (0, import_internal_utils8.makeVariants)({
filled: [],
outlined: ["bg-transparent", "border-sm", "border-current"],
tinted: [],
ghost: [],
contrast: ["bg-surface"]
}),
/**
* Color scheme of the button.
*/
intent: (0, import_internal_utils8.makeVariants)({
main: [],
support: [],
accent: [],
basic: [],
success: [],
alert: [],
danger: [],
info: [],
neutral: [],
surface: []
}),
/**
* Size of the button.
*/
size: (0, import_internal_utils8.makeVariants)({
sm: ["min-w-sz-32", "h-sz-32"],
md: ["min-w-sz-44", "h-sz-44"],
lg: ["min-w-sz-56", "h-sz-56"]
}),
/**
* Shape of the button.
*/
shape: (0, import_internal_utils8.makeVariants)({
rounded: ["rounded-lg"],
square: ["rounded-0"],
pill: ["rounded-full"]
}),
/**
* Disable the button, preventing user interaction and adding opacity.
*/
disabled: {
true: ["cursor-not-allowed", "opacity-dim-3"],
false: ["cursor-pointer"]
}
},
compoundVariants: [
...filledVariants,
...outlinedVariants,
...tintedVariants,
...ghostVariants,
...contrastVariants
],
defaultVariants: {
design: "filled",
intent: "main",
size: "md",
shape: "rounded"
}
}
);
// src/button/Button.tsx
var import_jsx_runtime15 = require("react/jsx-runtime");
var blockedEventHandlers = [
"onClick",
"onMouseDown",
"onMouseUp",
"onMouseEnter",
"onMouseLeave",
"onMouseOver",
"onMouseOut",
"onKeyDown",
"onKeyPress",
"onKeyUp",
"onSubmit"
];
var Button = ({
children,
design = "filled",
disabled = false,
intent = "main",
isLoading = false,
loadingLabel,
loadingText,
shape = "rounded",
size = "md",
asChild,
className,
ref,
...others
}) => {
const Component = asChild ? Slot : "button";
const shouldNotInteract = !!disabled || isLoading;
const disabledEventHandlers = (0, import_react7.useMemo)(() => {
const result = {};
if (shouldNotInteract) {
blockedEventHandlers.forEach((eventHandler) => result[eventHandler] = void 0);
}
return result;
}, [shouldNotInteract]);
const spinnerProps = {
size: "current",
className: loadingText ? "inline-block" : "absolute",
...loadingLabel && { "aria-label": loadingLabel }
};
return /* @__PURE__ */ (0, import_jsx_runtime15.jsx)(
Component,
{
"data-spark-component": "button",
...Component === "button" && { type: "button" },
ref,
className: buttonStyles({
className,
design,
disabled: shouldNotInteract,
intent,
shape,
size
}),
disabled: !!disabled,
"aria-busy": isLoading,
"aria-live": isLoading ? "assertive" : "off",
...others,
...disabledEventHandlers,
children: wrapPolymorphicSlot(
asChild,
children,
(slotted) => isLoading ? /* @__PURE__ */ (0, import_jsx_runtime15.jsxs)(import_jsx_runtime15.Fragment, { children: [
/* @__PURE__ */ (0, import_jsx_runtime15.jsx)(Spinner, { ...spinnerProps }),
loadingText && loadingText,
/* @__PURE__ */ (0, import_jsx_runtime15.jsx)(
"div",
{
"aria-hidden": true,
className: (0, import_class_variance_authority13.cx)("gap-md", loadingText ? "hidden" : "inline-flex opacity-0"),
children: slotted
}
)
] }) : slotted
)
}
);
};
Button.displayName = "Button";
// src/icon-button/IconButton.styles.tsx
var import_internal_utils9 = require("@spark-ui/internal-utils");
var import_class_variance_authority14 = require("class-variance-authority");
var iconButtonStyles = (0, import_class_variance_authority14.cva)(["pl-0 pr-0"], {
variants: {
/**
* Sets the size of the icon.
*/
size: (0, import_internal_utils9.makeVariants)({
sm: ["text-body-1"],
md: ["text-body-1"],
lg: ["text-display-3"]
})
}
});
// src/icon-button/IconButton.tsx
var import_jsx_runtime16 = require("react/jsx-runtime");
var IconButton = ({
design = "filled",
disabled = false,
intent = "main",
shape = "rounded",
size = "md",
className,
ref,
...others
}) => {
return /* @__PURE__ */ (0, import_jsx_runtime16.jsx)(
Button,
{
ref,
className: iconButtonStyles({ size, className }),
design,
disabled,
intent,
shape,
size,
...others
}
);
};
IconButton.displayName = "IconButton";
// src/stepper/StepperButton.tsx
var import_jsx_runtime17 = require("react/jsx-runtime");
var IncrementButton = ({
children,
design = "ghost",
intent = "neutral",
className,
ref: forwardedRef,
...rest
}) => {
const innerRef = (0, import_react8.useRef)(null);
const ref = forwardedRef && typeof forwardedRef !== "function" ? forwardedRef : innerRef;
const { incrementButtonProps } = useStepperContext();
const { buttonProps } = (0, import_button2.useButton)({ ...incrementButtonProps, ...rest }, ref);
return /* @__PURE__ */ (0, import_jsx_runtime17.jsx)(InputGroup2.TrailingAddon, { asChild: true, children: /* @__PURE__ */ (0, import_jsx_runtime17.jsx)(
IconButton,
{
ref,
design,
intent,
className,
"aria-label": buttonProps["aria-label"],
...buttonProps,
children: children || /* @__PURE__ */ (0, import_jsx_runtime17.jsx)(Icon, { children: /* @__PURE__ */ (0, import_jsx_runtime17.jsx)(import_Plus.Plus, {}) })
}
) });
};
var DecrementButton = ({
children,
design = "ghost",
intent = "neutral",
className,
ref: forwardedRef,
...rest
}) => {
const innerRef = (0, import_react8.useRef)(null);
const ref = forwardedRef && typeof forwardedRef !== "function" ? forwardedRef : innerRef;
const { decrementButtonProps } = useStepperContext();
const { buttonProps } = (0, import_button2.useButton)({ ...decrementButtonProps, ...rest }, ref);
return /* @__PURE__ */ (0, import_jsx_runtime17.jsx)(InputGroup2.LeadingAddon, { asChild: true, children: /* @__PURE__ */ (0, import_jsx_runtime17.jsx)(
IconButton,
{
ref,
design,
intent,
className,
"aria-label": buttonProps["aria-label"],
...buttonProps,
children: children || /* @__PURE__ */ (0, import_jsx_runtime17.jsx)(Icon, { children: /* @__PURE__ */ (0, import_jsx_runtime17.jsx)(import_Minus.Minus, {}) })
}
) });
};
var StepperIncrementButton = Object.assign(IncrementButton, {
id: "TrailingAddon"
});
var StepperDecrementButton = Object.assign(DecrementButton, {
id: "LeadingAddon"
});
IncrementButton.displayName = "Stepper.DecrementButton";
DecrementButton.displayName = "Stepper.DecrementButton";
// src/stepper/StepperInput.tsx
var import_use_merge_refs2 = require("@spark-ui/hooks/use-merge-refs");
var import_jsx_runtime18 = require("react/jsx-runtime");
var Input2 = ({ ref: forwardedRef, ...props }) => {
const { inputRef, inputProps } = useStepperContext();
const ref = (0, import_use_merge_refs2.useMergeRefs)(forwardedRef, inputRef);
const { className = "", ...remainingProps } = props;
return /* @__PURE__ */ (0, import_jsx_runtime18.jsx)(
Input,
{
ref,
...remainingProps,
...inputProps,
className: `min-w-sz-56 text-center ${className}`
}
);
};
var StepperInput = Object.assign(Input2, {
id: "Input"
});
Input2.displayName = "Stepper.Input";
// src/stepper/index.ts
var Stepper2 = Object.assign(Stepper, { IncrementButton: StepperIncrementButton, DecrementButton: StepperDecrementButton, Input: StepperInput });
Stepper2.displayName = "Stepper";
StepperIncrementButton.displayName = "Stepper.IncrementButton";
StepperDecrementButton.displayName = "Stepper.DecrementButton";
StepperInput.displayName = "Stepper.Input";
// Annotate the CommonJS export names for ESM import in node:
0 && (module.exports = {
Stepper
});
//# sourceMappingURL=index.js.map