@spark-ui/components
Version:
Spark (Leboncoin design system) components.
1,701 lines (1,662 loc) • 78.9 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/combobox/index.ts
var combobox_exports = {};
__export(combobox_exports, {
Combobox: () => Combobox2,
ComboboxProvider: () => ComboboxProvider,
useComboboxContext: () => useComboboxContext
});
module.exports = __toCommonJS(combobox_exports);
// src/combobox/ComboboxContext.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_downshift3 = require("downshift");
var import_react7 = require("react");
// src/popover/Popover.tsx
var import_radix_ui = require("radix-ui");
// src/popover/PopoverContext.tsx
var import_react = require("react");
var import_jsx_runtime = require("react/jsx-runtime");
var PopoverContext = (0, import_react.createContext)(null);
var ID_PREFIX = ":popover";
var PopoverProvider = ({
children,
intent
}) => {
const [headerId, setHeaderId] = (0, import_react.useState)(null);
return /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
PopoverContext.Provider,
{
value: {
headerId,
setHeaderId,
intent
},
children
}
);
};
var usePopover = () => {
const context = (0, import_react.useContext)(PopoverContext);
if (!context) {
throw Error("usePopover must be used within a Popover provider");
}
return context;
};
// src/popover/Popover.tsx
var import_jsx_runtime2 = require("react/jsx-runtime");
var Popover = ({ children, intent = "surface", modal = false, ...rest }) => {
return /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(PopoverProvider, { intent, children: /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(import_radix_ui.Popover.Root, { "data-spark-component": "popover", modal, ...rest, children }) });
};
Popover.displayName = "Popover";
// src/popover/PopoverAnchor.tsx
var import_radix_ui2 = require("radix-ui");
var import_jsx_runtime3 = require("react/jsx-runtime");
var Anchor = ({ asChild = false, children, ref, ...rest }) => /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(import_radix_ui2.Popover.Anchor, { "data-spark-component": "popover-anchor", ref, asChild, ...rest, children });
Anchor.displayName = "Popover.Anchor";
// src/popover/PopoverArrow.tsx
var import_class_variance_authority = require("class-variance-authority");
var import_radix_ui3 = require("radix-ui");
var import_jsx_runtime4 = require("react/jsx-runtime");
var Arrow = ({
asChild = false,
width = 16,
height = 8,
className,
ref,
...rest
}) => {
const { intent } = usePopover();
const styles4 = (0, import_class_variance_authority.cva)("visible", {
variants: {
intent: {
surface: "fill-surface",
main: "fill-main-container",
support: "fill-support-container",
accent: "fill-accent-container",
basic: "fill-basic-container",
success: "fill-success-container",
alert: "fill-alert-container",
danger: "fill-error-container",
info: "fill-info-container",
neutral: "fill-neutral-container"
}
},
defaultVariants: {
intent: "surface"
}
});
return /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(
import_radix_ui3.Popover.Arrow,
{
"data-spark-component": "popover-arrow",
ref,
className: styles4({ intent, className }),
asChild,
width,
height,
...rest
}
);
};
Arrow.displayName = "Popover.Arrow";
// src/popover/PopoverCloseButton.tsx
var import_Close = require("@spark-ui/icons/Close");
var import_class_variance_authority7 = require("class-variance-authority");
var import_radix_ui5 = require("radix-ui");
// src/icon/Icon.tsx
var import_react3 = require("react");
// src/slot/Slot.tsx
var import_radix_ui4 = require("radix-ui");
var import_react2 = require("react");
var import_jsx_runtime5 = require("react/jsx-runtime");
var Slottable = import_radix_ui4.Slot.Slottable;
var Slot = ({ ref, ...props }) => {
return /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(import_radix_ui4.Slot.Root, { ref, ...props });
};
var wrapPolymorphicSlot = (asChild, children, callback) => {
if (!asChild) return callback(children);
return (0, import_react2.isValidElement)(children) ? (0, import_react2.cloneElement)(
children,
void 0,
callback(children.props.children)
) : null;
};
// src/visually-hidden/VisuallyHidden.tsx
var import_jsx_runtime6 = require("react/jsx-runtime");
var VisuallyHidden = ({ asChild = false, ref, ...props }) => {
const Component = asChild ? Slot : "span";
return /* @__PURE__ */ (0, import_jsx_runtime6.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_authority2 = require("class-variance-authority");
var iconStyles = (0, import_class_variance_authority2.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_runtime7 = require("react/jsx-runtime");
var Icon = ({
label,
className,
size = "current",
intent = "current",
children,
...others
}) => {
const child = import_react3.Children.only(children);
return /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)(import_jsx_runtime7.Fragment, { children: [
(0, import_react3.cloneElement)(child, {
className: iconStyles({ className, size, intent }),
"data-spark-component": "icon",
"aria-hidden": "true",
focusable: "false",
...others
}),
label && /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(VisuallyHidden, { children: label })
] });
};
Icon.displayName = "Icon";
// src/button/Button.tsx
var import_class_variance_authority5 = require("class-variance-authority");
var import_react4 = require("react");
// src/spinner/Spinner.styles.tsx
var import_internal_utils2 = require("@spark-ui/internal-utils");
var import_class_variance_authority3 = require("class-variance-authority");
var defaultVariants = {
intent: "current",
size: "current",
isBackgroundVisible: false
};
var spinnerStyles = (0, import_class_variance_authority3.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_runtime8 = require("react/jsx-runtime");
var Spinner = ({
className,
size = "current",
intent = "current",
label,
isBackgroundVisible,
ref,
...others
}) => {
return /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(
"span",
{
role: "status",
"data-spark-component": "spinner",
ref,
className: spinnerStyles({ className, size, intent, isBackgroundVisible }),
...others,
children: label && /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(VisuallyHidden, { children: label })
}
);
};
// src/button/Button.styles.tsx
var import_internal_utils8 = require("@spark-ui/internal-utils");
var import_class_variance_authority4 = 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_authority4.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_runtime9 = 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_react4.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_runtime9.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_runtime9.jsxs)(import_jsx_runtime9.Fragment, { children: [
/* @__PURE__ */ (0, import_jsx_runtime9.jsx)(Spinner, { ...spinnerProps }),
loadingText && loadingText,
/* @__PURE__ */ (0, import_jsx_runtime9.jsx)(
"div",
{
"aria-hidden": true,
className: (0, import_class_variance_authority5.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_authority6 = require("class-variance-authority");
var iconButtonStyles = (0, import_class_variance_authority6.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_runtime10 = require("react/jsx-runtime");
var IconButton = ({
design = "filled",
disabled = false,
intent = "main",
shape = "rounded",
size = "md",
className,
ref,
...others
}) => {
return /* @__PURE__ */ (0, import_jsx_runtime10.jsx)(
Button,
{
ref,
className: iconButtonStyles({ size, className }),
design,
disabled,
intent,
shape,
size,
...others
}
);
};
IconButton.displayName = "IconButton";
// src/popover/PopoverCloseButton.tsx
var import_jsx_runtime11 = require("react/jsx-runtime");
var CloseButton = ({
"aria-label": ariaLabel,
className,
ref,
...rest
}) => {
return /* @__PURE__ */ (0, import_jsx_runtime11.jsx)(
import_radix_ui5.Popover.Close,
{
"data-spark-component": "popover-close-button",
ref,
className: (0, import_class_variance_authority7.cx)("right-md top-md absolute", className),
asChild: true,
...rest,
children: /* @__PURE__ */ (0, import_jsx_runtime11.jsx)(IconButton, { size: "sm", intent: "neutral", design: "ghost", "aria-label": ariaLabel, children: /* @__PURE__ */ (0, import_jsx_runtime11.jsx)(Icon, { children: /* @__PURE__ */ (0, import_jsx_runtime11.jsx)(import_Close.Close, {}) }) })
}
);
};
CloseButton.displayName = "Popover.CloseButton";
// src/popover/PopoverContent.tsx
var import_radix_ui6 = require("radix-ui");
// src/popover/PopoverContent.styles.ts
var import_class_variance_authority8 = require("class-variance-authority");
var styles = (0, import_class_variance_authority8.cva)(
[
"rounded-md",
"shadow-sm",
"focus-visible:outline-hidden focus-visible:u-outline",
"max-h-(--radix-popper-available-height) overflow-y-auto"
],
{
variants: {
intent: {
surface: "bg-surface text-on-surface",
main: "bg-main-container text-on-main-container",
support: "bg-support-container text-on-support-container",
accent: "bg-accent-container text-on-accent-container",
basic: "bg-basic-container text-on-basic-container",
success: "bg-success-container text-on-success-container",
alert: "bg-alert-container text-on-alert-container",
danger: "bg-error-container text-on-error-container",
info: "bg-info-container text-on-info-container",
neutral: "bg-neutral-container text-on-neutral-container"
},
matchTriggerWidth: {
true: "w-(--radix-popper-anchor-width)"
},
enforceBoundaries: {
true: ["max-w-(--radix-popper-available-width)"]
},
inset: {
true: "overflow-hidden",
false: "p-lg"
},
elevation: {
dropdown: "z-dropdown",
popover: "z-popover"
}
},
compoundVariants: [
{
inset: false,
/**
* When there is a close button, padding to the right side must be adjusted to avoid content overlapping with it.
*/
class: "has-data-[spark-component=popover-close-button]:pr-3xl"
},
{
enforceBoundaries: false,
matchTriggerWidth: false,
class: "max-w-[min(var(--spacing-sz-384),100vw)]"
}
],
defaultVariants: {
matchTriggerWidth: false,
enforceBoundaries: false,
inset: false,
intent: "surface",
elevation: "popover"
}
}
);
// src/popover/PopoverContent.tsx
var import_jsx_runtime12 = require("react/jsx-runtime");
var Content = ({
// Spark props
className,
children,
matchTriggerWidth = false,
// Radix props
align = "center",
arrowPadding = 16,
// In order not to overlap the arrow on the rounded corners of the popover.
asChild = false,
avoidCollisions = true,
"aria-labelledby": ariaLabelledBy,
collisionBoundary,
collisionPadding = 0,
hideWhenDetached = false,
side = "bottom",
sideOffset = 8,
sticky = "partial",
inset = false,
elevation = "popover",
ref,
...rest
}) => {
const { headerId, intent } = usePopover();
return /* @__PURE__ */ (0, import_jsx_runtime12.jsx)(
import_radix_ui6.Popover.Content,
{
"aria-labelledby": headerId || ariaLabelledBy,
className: styles({
enforceBoundaries: !!collisionBoundary,
matchTriggerWidth,
inset,
elevation,
intent,
className
}),
"data-spark-component": "popover-content",
ref,
...{
align,
arrowPadding,
asChild,
avoidCollisions,
collisionBoundary,
collisionPadding,
hideWhenDetached,
side,
sideOffset,
sticky
},
...rest,
children
}
);
};
Content.displayName = "Popover.Content";
// src/popover/PopoverHeader.tsx
var import_class_variance_authority9 = require("class-variance-authority");
var import_react5 = require("react");
var import_jsx_runtime13 = require("react/jsx-runtime");
var Header = ({ children, className, ref, ...rest }) => {
const id = `${ID_PREFIX}-header-${(0, import_react5.useId)()}`;
const { setHeaderId } = usePopover();
(0, import_react5.useLayoutEffect)(() => {
setHeaderId(id);
return () => setHeaderId(null);
}, [id, setHeaderId]);
return /* @__PURE__ */ (0, import_jsx_runtime13.jsx)("header", { id, ref, className: (0, import_class_variance_authority9.cx)("mb-md text-headline-2", className), ...rest, children });
};
Header.displayName = "Popover.Header";
// src/popover/PopoverPortal.tsx
var import_radix_ui7 = require("radix-ui");
var import_jsx_runtime14 = require("react/jsx-runtime");
var Portal = ({ children, ...rest }) => /* @__PURE__ */ (0, import_jsx_runtime14.jsx)(import_radix_ui7.Popover.Portal, { ...rest, children });
Portal.displayName = "Popover.Portal";
// src/popover/PopoverTrigger.tsx
var import_radix_ui8 = require("radix-ui");
var import_jsx_runtime15 = require("react/jsx-runtime");
var Trigger = ({ asChild = false, children, ref, ...rest }) => /* @__PURE__ */ (0, import_jsx_runtime15.jsx)(
import_radix_ui8.Popover.Trigger,
{
"data-spark-component": "popover-trigger",
ref,
asChild,
...rest,
children
}
);
Trigger.displayName = "Popover.Trigger";
// src/popover/index.ts
var Popover2 = Object.assign(Popover, {
Anchor,
Arrow,
CloseButton,
Content,
Header,
Portal,
Trigger
});
Popover2.displayName = "Popover";
Anchor.displayName = "Popover.Anchor";
Arrow.displayName = "Popover.Arrow";
CloseButton.displayName = "Popover.CloseButton";
Content.displayName = "Popover.Content";
Header.displayName = "Popover.Header";
Portal.displayName = "Popover.Portal";
Trigger.displayName = "Popover.Trigger";
// src/combobox/useCombobox/multipleSelectionReducer.ts
var import_downshift = require("downshift");
// src/combobox/utils/index.ts
var import_react6 = require("react");
function getIndexByKey(map, targetKey) {
let index = 0;
for (const [key] of map.entries()) {
if (key === targetKey) {
return index;
}
index++;
}
return -1;
}
var getKeyAtIndex = (map, index) => {
let i = 0;
for (const key of map.keys()) {
if (i === index) return key;
i++;
}
return void 0;
};
var getElementByIndex = (map, index) => {
const key = getKeyAtIndex(map, index);
return key !== void 0 ? map.get(key) : void 0;
};
var getElementDisplayName = (element) => {
return element ? element.type.displayName : "";
};
var getOrderedItems = (children, result = []) => {
import_react6.Children.forEach(children, (child) => {
if (!(0, import_react6.isValidElement)(child)) return;
if (getElementDisplayName(child) === "Combobox.Item") {
const childProps = child.props;
result.push({
value: childProps.value,
disabled: !!childProps.disabled,
text: getItemText(childProps.children)
});
}
if (child.props.children) {
getOrderedItems(child.props.children, result);
}
});
return result;
};
var findNestedItemText = (children) => {
if (!children) return "";
for (const child of import_react6.Children.toArray(children)) {
if ((0, import_react6.isValidElement)(child)) {
const childElement = child;
if (getElementDisplayName(childElement) === "Combobox.ItemText") {
return childElement.props.children;
}
const foundText = findNestedItemText(childElement.props.children);
if (foundText) return foundText;
}
}
return "";
};
var getItemText = (children) => {
return typeof children === "string" ? children : findNestedItemText(children);
};
var getItemsFromChildren = (children) => {
const newMap = /* @__PURE__ */ new Map();
getOrderedItems(children).forEach((itemData) => {
newMap.set(itemData.value, itemData);
});
return newMap;
};
var hasChildComponent = (children, displayName) => {
return import_react6.Children.toArray(children).some((child) => {
if (!(0, import_react6.isValidElement)(child)) return false;
if (getElementDisplayName(child) === displayName) {
return true;
} else if (child.props.children) {
return hasChildComponent(child.props.children, displayName);
}
return false;
});
};
var findElement = (children, value) => {
return import_react6.Children.toArray(children).filter(import_react6.isValidElement).find((child) => value === getElementDisplayName(child) || "");
};
// src/combobox/useCombobox/multipleSelectionReducer.ts
var multipleSelectionReducer = ({
multiselect,
selectedItems,
allowCustomValue = false,
setSelectedItems,
triggerAreaRef,
items
}) => {
const reducer = (_, { changes, type }) => {
const isFocusInsideTriggerArea = triggerAreaRef.current?.contains?.(document.activeElement);
switch (type) {
case import_downshift.useCombobox.stateChangeTypes.InputClick:
return {
...changes,
isOpen: true
// keep menu opened
};
case import_downshift.useCombobox.stateChangeTypes.InputKeyDownEnter:
case import_downshift.useCombobox.stateChangeTypes.ItemClick: {
const newState = { ...changes };
if (changes.selectedItem != null) {
newState.inputValue = "";
newState.isOpen = true;
const highlightedIndex = getIndexByKey(items, changes.selectedItem.value);
newState.highlightedIndex = highlightedIndex;
const isAlreadySelected = multiselect.selectedItems.some(
(selectedItem) => selectedItem.value === changes.selectedItem?.value
);
const updatedItems = isAlreadySelected ? selectedItems.filter((item) => item.value !== changes.selectedItem?.value) : [...selectedItems, changes.selectedItem];
setSelectedItems(updatedItems);
}
return newState;
}
case import_downshift.useCombobox.stateChangeTypes.ToggleButtonClick:
return {
...changes,
inputValue: allowCustomValue ? changes.inputValue : ""
};
case import_downshift.useCombobox.stateChangeTypes.InputChange:
return {
...changes,
selectedItem: changes.highlightedIndex === -1 ? null : changes.selectedItem
};
case import_downshift.useCombobox.stateChangeTypes.InputBlur:
return {
...changes,
inputValue: allowCustomValue ? changes.inputValue : "",
isOpen: isFocusInsideTriggerArea
};
default:
return changes;
}
};
return reducer;
};
// src/combobox/useCombobox/singleSelectionReducer.ts
var import_downshift2 = require("downshift");
var singleSelectionReducer = ({
filteredItems,
allowCustomValue = false,
setSelectedItem
}) => {
const reducer = (state, { changes, type }) => {
const exactMatch = filteredItems.find(
(item) => item.text.toLowerCase() === state.inputValue.toLowerCase()
);
switch (type) {
case import_downshift2.useCombobox.stateChangeTypes.InputKeyDownEscape:
if (!changes.selectedItem) {
setSelectedItem(null);
}
return changes;
case import_downshift2.useCombobox.stateChangeTypes.ItemClick:
case import_downshift2.useCombobox.stateChangeTypes.InputKeyDownEnter:
if (changes.selectedItem) {
setSelectedItem(changes.selectedItem);
}
return changes;
case import_downshift2.useCombobox.stateChangeTypes.InputClick:
return { ...changes, isOpen: true };
case import_downshift2.useCombobox.stateChangeTypes.ToggleButtonClick:
case import_downshift2.useCombobox.stateChangeTypes.InputBlur:
if (allowCustomValue) return changes;
if (state.inputValue === "") {
setSelectedItem(null);
return { ...changes, selectedItem: null };
}
if (exactMatch) {
setSelectedItem(exactMatch);
return { ...changes, selectedItem: exactMatch, inputValue: exactMatch.text };
}
if (state.selectedItem) {
return { ...changes, inputValue: state.selectedItem.text };
}
return { ...changes, inputValue: "" };
default:
return changes;
}
};
return reducer;
};
// src/combobox/ComboboxContext.tsx
var import_jsx_runtime16 = require("react/jsx-runtime");
var ComboboxContext = (0, import_react7.createContext)(null);
var getFilteredItemsMap = (map, inputValue) => {
if (!inputValue) return map;
return new Map(
Array.from(map).filter(([_, { text }]) => text.toLowerCase().includes(inputValue.toLowerCase()))
);
};
var ID_PREFIX2 = ":combobox";
var ComboboxProvider = ({
children,
state: stateProp,
allowCustomValue = false,
filtering = "auto",
disabled: disabledProp = false,
multiple = false,
readOnly: readOnlyProp = false,
wrap = true,
// Value
value: controlledValue,
defaultValue,
onValueChange,
// Open
open: controlledOpen,
defaultOpen,
onOpenChange,
isLoading
}) => {
const isMounted = (0, import_react7.useRef)(false);
const [inputValue, setInputValue] = (0, import_react7.useState)("");
const [isTyping, setIsTyping] = (0, import_react7.useState)(filtering === "strict");
const triggerAreaRef = (0, import_react7.useRef)(null);
const innerInputRef = (0, import_react7.useRef)(null);
const [onInputValueChange, setOnInputValueChange] = (0, import_react7.useState)(null);
const [comboboxValue] = (0, import_use_combined_state.useCombinedState)(controlledValue, defaultValue);
const shouldFilterItems = filtering === "strict" || filtering === "auto" && isTyping;
const [itemsMap, setItemsMap] = (0, import_react7.useState)(getItemsFromChildren(children));
const [filteredItemsMap, setFilteredItems] = (0, import_react7.useState)(
shouldFilterItems ? getFilteredItemsMap(itemsMap, inputValue) : itemsMap
);
const [selectedItem, setSelectedItem] = (0, import_react7.useState)(
itemsMap.get(comboboxValue) || null
);
const [selectedItems, setSelectedItems] = (0, import_react7.useState)(
comboboxValue ? [...itemsMap.values()].filter((item) => comboboxValue.includes(item.value)) : []
);
const onInternalSelectedItemChange = (item) => {
setIsTyping(false);
if (item?.value !== selectedItem?.value) {
setSelectedItem(item);
setTimeout(() => {
onValueChange?.(item?.value);
}, 0);
}
};
const onInternalSelectedItemsChange = (items) => {
setSelectedItems(items);
setTimeout(() => {
onValueChange?.(items.map((i) => i.value));
}, 0);
};
(0, import_react7.useEffect)(() => {
if (!isMounted.current) {
isMounted.current = true;
return;
}
if (multiple) {
const newSelectedItems = comboboxValue.reduce(
(accum, value) => {
const match = itemsMap.get(value);
return match ? [...accum, match] : accum;
},
[]
);
setSelectedItems(comboboxValue ? newSelectedItems : []);
} else {
setSelectedItem(itemsMap.get(comboboxValue) || null);
}
}, [multiple ? JSON.stringify(comboboxValue) : comboboxValue]);
const field = (0, import_form_field.useFormFieldControl)();
const internalFieldLabelID = `${ID_PREFIX2}-label-${(0, import_react7.useId)()}`;
const internalFieldID = `${ID_PREFIX2}-field-${(0, import_react7.useId)()}`;
const id = field.id || internalFieldID;
const labelId = field.labelId || internalFieldLabelID;
const state = field.state || stateProp;
const disabled = field.disabled ?? disabledProp;
const readOnly = field.readOnly ?? readOnlyProp;
const [hasPopover, setHasPopover] = (0, import_react7.useState)(
hasChildComponent(children, "Combobox.Popover")
);
const [lastInteractionType, setLastInteractionType] = (0, import_react7.useState)("mouse");
(0, import_react7.useEffect)(() => {
setFilteredItems(shouldFilterItems ? getFilteredItemsMap(itemsMap, inputValue) : itemsMap);
}, [inputValue, itemsMap]);
const multiselect = (0, import_downshift3.useMultipleSelection)({
selectedItems,
stateReducer: (state2, { type, changes }) => {
const types = import_downshift3.useMultipleSelection.stateChangeTypes;
switch (type) {
case types.SelectedItemKeyDownBackspace:
case types.SelectedItemKeyDownDelete: {
onInternalSelectedItemsChange(changes.selectedItems || []);
let activeIndex;
if (type === types.SelectedItemKeyDownDelete) {
const isLastItem = state2?.activeIndex === changes.selectedItems?.length;
activeIndex = isLastItem ? -1 : state2.activeIndex;
} else {
const hasItemBefore = (changes?.activeIndex || 0) - 1 >= 0;
activeIndex = hasItemBefore ? state2.activeIndex - 1 : changes?.activeIndex;
}
return {
...changes,
activeIndex
};
}
case types.SelectedItemClick:
if (innerInputRef.current) {
innerInputRef.current.focus();
}
return {
...changes,
activeIndex: -1
// the focus will remain on the input
};
case types.FunctionRemoveSelectedItem:
return {
...changes,
activeIndex: -1
// the focus will remain on the input
};
case types.DropdownKeyDownNavigationPrevious:
downshift.closeMenu();
return changes;
default:
return changes;
}
}
});
const filteredItems = Array.from(filteredItemsMap.values());
(0, import_react7.useEffect)(() => {
onInputValueChange?.(inputValue || "");
}, [inputValue]);
const downshift = (0, import_downshift3.useCombobox)({
inputId: id,
items: filteredItems,
selectedItem: multiple ? void 0 : selectedItem,
id,
labelId,
// Input
inputValue,
onInputValueChange: ({ inputValue: newInputValue }) => {
setInputValue(newInputValue);
if (shouldFilterItems) {
const filtered = getFilteredItemsMap(itemsMap, newInputValue || "");
setFilteredItems(filtered);
}
},
// Open
initialIsOpen: defaultOpen,
...controlledOpen != null && { isOpen: controlledOpen },
onIsOpenChange: (changes) => {
if (changes.isOpen != null) {
onOpenChange?.(changes.isOpen);
}
},
// Custom Spark item object parsing
itemToString: (item) => {
return item?.text;
},
isItemDisabled: (item) => {
const isFilteredOut = !!inputValue && !filteredItems.some((filteredItem) => {
return item.value === filteredItem.value;
});
return item.disabled || isFilteredOut;
},
// Main reducer
stateReducer: multiple ? multipleSelectionReducer({
multiselect,
selectedItems,
allowCustomValue,
setSelectedItems: onInternalSelectedItemsChange,
triggerAreaRef,
items: itemsMap
}) : singleSelectionReducer({
allowCustomValue,
setSelectedItem: onInternalSelectedItemChange,
filteredItems: [...filteredItemsMap.values()]
}),
/**
* Downshift default behaviour is to scroll into view the highlighted item when the dropdown opens. This behaviour is not stable and scrolls the dropdown to the bottom of the screen.
*/
scrollIntoView: (node) => {
if (node) {
node.scrollIntoView({ block: "nearest" });
}
return void 0;
}
});
(0, import_react7.useEffect)(() => {
const newMap = getItemsFromChildren(children);
const previousItems = [...itemsMap.values()];
const newItems = [...newMap.values()];
const hasItemsChanges = previousItems.length !== newItems.length || previousItems.some((item, index) => {
const hasUpdatedValue = item.value !== newItems[index]?.value;
const hasUpdatedText = item.text !== newItems[index]?.text;
return hasUpdatedValue || hasUpdatedText;
});
if (hasItemsChanges) {
setItemsMap(newMap);
}
}, [children]);
const [WrapperComponent, wrapperProps] = hasPopover ? [Popover2, { open: true }] : [import_react7.Fragment, {}];
return /* @__PURE__ */ (0, import_jsx_runtime16.jsx)(
ComboboxContext.Provider,
{
value: {
// Data
itemsMap,
filteredItemsMap,
highlightedItem: getElementByIndex(filteredItemsMap, downshift.highlightedIndex),
// State
multiple,
disabled,
readOnly,
hasPopover,
setHasPopover