UNPKG

@spark-ui/components

Version:

Spark (Leboncoin design system) components.

581 lines (558 loc) 17.6 kB
"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/select/index.ts var select_exports = {}; __export(select_exports, { Select: () => Select2, SelectProvider: () => SelectProvider, useSelectContext: () => useSelectContext }); module.exports = __toCommonJS(select_exports); // src/select/SelectContext.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_react2 = require("react"); // src/select/utils.ts var import_react = require("react"); var findElement = (children) => (name) => { const validChildren = import_react.Children.toArray(children).filter(import_react.isValidElement); return validChildren.find((child) => { return getElementDisplayName(child)?.includes(name); }); }; var getElementDisplayName = (element) => { return element ? element.type.displayName : ""; }; var getOrderedItems = (children, result = []) => { import_react.Children.forEach(children, (child) => { if (!(0, import_react.isValidElement)(child)) return; if (getElementDisplayName(child) === "Select.Item" || getElementDisplayName(child) === "Select.Placeholder") { const childProps = child.props; result.push({ value: childProps.value, disabled: !!childProps.disabled, text: childProps.children }); } if (child.props.children) { getOrderedItems(child.props.children, result); } }); return result; }; var getItemsFromChildren = (children) => { const newMap = /* @__PURE__ */ new Map(); getOrderedItems(children).forEach((itemData) => { newMap.set(itemData.value, itemData); }); return newMap; }; // src/select/SelectContext.tsx var import_jsx_runtime = require("react/jsx-runtime"); var SelectContext = (0, import_react2.createContext)(null); var ID_PREFIX = ":select"; var SelectProvider = ({ children, defaultValue, value: valueProp, onValueChange, disabled: disabledProp = false, readOnly: readOnlyProp = false, state: stateProp, itemsComponent, name: nameProp, required: requiredProp }) => { const [value, setValue] = (0, import_use_combined_state.useCombinedState)(valueProp, defaultValue, onValueChange); const [placeholder, setPlaceholder] = (0, import_react2.useState)(void 0); const [itemsMap, setItemsMap] = (0, import_react2.useState)(getItemsFromChildren(itemsComponent)); const [ariaLabel, setAriaLabel] = (0, import_react2.useState)(); const firstItem = itemsMap.entries().next()?.value?.[1]; const selectedItem = typeof value === "string" ? itemsMap.get(value) : firstItem; const isControlled = valueProp != null; const field = (0, import_form_field.useFormFieldControl)(); const state = field.state || stateProp; const internalFieldID = `${ID_PREFIX}-field-${(0, import_react2.useId)()}`; const fieldId = field.id || internalFieldID; const fieldLabelId = field.labelId; const disabled = field.disabled ?? disabledProp; const readOnly = field.readOnly ?? readOnlyProp; const name = field.name ?? nameProp; const required = !!(field.isRequired ?? requiredProp); (0, import_react2.useEffect)(() => { const newMap = getItemsFromChildren(itemsComponent); 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]); return /* @__PURE__ */ (0, import_jsx_runtime.jsx)( SelectContext.Provider, { value: { disabled, readOnly, itemsMap, state, itemsComponent, selectedItem, setValue, isControlled, onValueChange, ariaLabel, setAriaLabel, fieldId, fieldLabelId, name, required, placeholder, setPlaceholder }, children } ); }; var useSelectContext = () => { const context = (0, import_react2.useContext)(SelectContext); if (!context) { throw Error("useSelectContext must be used within a Select provider"); } return context; }; // src/select/Select.tsx var import_jsx_runtime2 = require("react/jsx-runtime"); var Select = ({ children, ...props }) => { const finder = findElement(children); const trigger = finder("Trigger"); const items = finder("Items"); return /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(SelectProvider, { ...props, itemsComponent: items, children: trigger }); }; Select.displayName = "Select"; // src/select/SelectGroup.tsx var import_class_variance_authority = require("class-variance-authority"); // src/select/SelectItemsGroupContext.tsx var import_react3 = require("react"); var import_jsx_runtime3 = require("react/jsx-runtime"); var SelectGroupContext = (0, import_react3.createContext)(null); var SelectGroupProvider = ({ children }) => { const [groupLabel, setGroupLabel] = (0, import_react3.useState)(""); return /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(SelectGroupContext.Provider, { value: { groupLabel, setGroupLabel }, children }); }; var useSelectGroupContext = () => { const context = (0, import_react3.useContext)(SelectGroupContext); if (!context) { throw Error("useSelectGroupContext must be used within a SelectGroup provider"); } return context; }; // src/select/SelectGroup.tsx var import_jsx_runtime4 = require("react/jsx-runtime"); var Group = ({ children, ref: forwardedRef, ...props }) => { return /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(SelectGroupProvider, { children: /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(GroupContent, { ref: forwardedRef, ...props, children }) }); }; var GroupContent = ({ children, className, ref: forwardedRef }) => { const { groupLabel } = useSelectGroupContext(); return /* @__PURE__ */ (0, import_jsx_runtime4.jsx)( "optgroup", { "data-spark-component": "select-group", ref: forwardedRef, className: (0, import_class_variance_authority.cx)(className), label: groupLabel, children } ); }; Group.displayName = "Select.Group"; // src/select/SelectItem.tsx var import_jsx_runtime5 = require("react/jsx-runtime"); var Item = ({ disabled = false, value, children, ref: forwardedRef }) => { return /* @__PURE__ */ (0, import_jsx_runtime5.jsx)( "option", { "data-spark-component": "select-item", ref: forwardedRef, value, disabled, children }, value ); }; Item.displayName = "Select.Item"; // src/select/SelectItems.tsx var import_class_variance_authority2 = require("class-variance-authority"); var import_jsx_runtime6 = require("react/jsx-runtime"); var styles = (0, import_class_variance_authority2.cva)( [ "absolute left-0 top-0 size-full rounded-lg opacity-0", "min-h-sz-44", // outline styles "ring-1 outline-hidden ring-inset focus:ring-2" ], { variants: { state: { undefined: "ring-outline focus:ring-outline-high", error: "ring-error", alert: "ring-alert", success: "ring-success" }, disabled: { true: "cursor-not-allowed" }, readOnly: { true: "cursor-default" } }, compoundVariants: [ { disabled: false, state: void 0, class: "hover:ring-outline-high" } ] } ); var Items = ({ children, className, ref, ...rest }) => { const { state, disabled, readOnly, ariaLabel, fieldLabelId, isControlled, onValueChange, selectedItem, setValue, name, required, fieldId } = useSelectContext(); const handleChange = (event) => { if (isControlled) { event.preventDefault(); onValueChange?.(event.target.value); } else { setValue(event.target.value); } }; return /* @__PURE__ */ (0, import_jsx_runtime6.jsx)( "select", { "data-spark-component": "select-items", ref, disabled: disabled || readOnly, name, required, "aria-labelledby": fieldLabelId, ...ariaLabel && { "aria-label": ariaLabel }, className: styles({ className, state, disabled, readOnly }), value: selectedItem?.value, onChange: handleChange, id: fieldId, ...rest, children } ); }; Items.displayName = "Select.Items"; // src/select/SelectLabel.tsx var import_react4 = require("react"); var Label = ({ children }) => { const { setGroupLabel } = useSelectGroupContext(); (0, import_react4.useEffect)(() => { setGroupLabel(children); }, [children]); return null; }; Label.displayName = "Select.Label"; // src/icon/Icon.tsx var import_react6 = require("react"); // src/slot/Slot.tsx var import_radix_ui = require("radix-ui"); var import_react5 = require("react"); var import_jsx_runtime7 = require("react/jsx-runtime"); var Slottable = import_radix_ui.Slot.Slottable; var Slot = ({ ref, ...props }) => { return /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(import_radix_ui.Slot.Root, { ref, ...props }); }; // src/visually-hidden/VisuallyHidden.tsx var import_jsx_runtime8 = require("react/jsx-runtime"); var VisuallyHidden = ({ asChild = false, ref, ...props }) => { const Component = asChild ? Slot : "span"; return /* @__PURE__ */ (0, import_jsx_runtime8.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_authority3 = require("class-variance-authority"); var iconStyles = (0, import_class_variance_authority3.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_runtime9 = require("react/jsx-runtime"); var Icon = ({ label, className, size = "current", intent = "current", children, ...others }) => { const child = import_react6.Children.only(children); return /* @__PURE__ */ (0, import_jsx_runtime9.jsxs)(import_jsx_runtime9.Fragment, { children: [ (0, import_react6.cloneElement)(child, { className: iconStyles({ className, size, intent }), "data-spark-component": "icon", "aria-hidden": "true", focusable: "false", ...others }), label && /* @__PURE__ */ (0, import_jsx_runtime9.jsx)(VisuallyHidden, { children: label }) ] }); }; Icon.displayName = "Icon"; // src/select/SelectLeadingIcon.tsx var import_jsx_runtime10 = require("react/jsx-runtime"); var LeadingIcon = ({ children }) => { return /* @__PURE__ */ (0, import_jsx_runtime10.jsx)(Icon, { size: "sm", className: "shrink-0", children }); }; LeadingIcon.displayName = "Select.LeadingIcon"; // src/select/SelectPlaceholder.tsx var import_react7 = require("react"); var import_jsx_runtime11 = require("react/jsx-runtime"); var Placeholder = ({ disabled = false, children, ref: forwardedRef }) => { const { setPlaceholder } = useSelectContext(); (0, import_react7.useEffect)(() => { setPlaceholder(children); }, [children]); return /* @__PURE__ */ (0, import_jsx_runtime11.jsx)( "option", { "data-spark-component": "select-placeholder", ref: forwardedRef, value: "", disabled, children }, "placeholder" ); }; Placeholder.displayName = "Select.Placeholder"; // src/select/SelectTrigger.tsx var import_ArrowHorizontalDown = require("@spark-ui/icons/ArrowHorizontalDown"); var import_react8 = require("react"); // src/select/SelectTrigger.styles.tsx var import_class_variance_authority4 = require("class-variance-authority"); var styles2 = (0, import_class_variance_authority4.cva)( [ "relative flex w-full items-center justify-between", "min-h-sz-44 rounded-lg px-lg", "text-body-1", // outline styles "ring-1 outline-hidden ring-inset" ], { variants: { state: { undefined: "ring-outline", error: "ring-error", alert: "ring-alert", success: "ring-success" }, disabled: { false: "focus-within:ring-2" }, readOnly: { true: "" } }, compoundVariants: [ { readOnly: false, disabled: false, class: "bg-surface text-on-surface" }, { readOnly: true, class: "bg-on-surface/dim-5 text-on-surface cursor-default" }, { disabled: true, class: ["bg-on-surface/dim-5 text-on-surface/dim-3", "cursor-not-allowed"] }, { disabled: false, state: void 0, class: "hover:ring-outline-high focus-within:ring-outline-high" } ] } ); // src/select/SelectTrigger.tsx var import_jsx_runtime12 = require("react/jsx-runtime"); var Trigger = ({ "aria-label": ariaLabel, children, className, ref: forwardedRef }) => { const { disabled, readOnly, state, setAriaLabel, itemsComponent } = useSelectContext(); (0, import_react8.useEffect)(() => { if (ariaLabel) { setAriaLabel(ariaLabel); } }, [ariaLabel]); return /* @__PURE__ */ (0, import_jsx_runtime12.jsxs)( "div", { "data-spark-component": "select-trigger", ref: forwardedRef, className: styles2({ className, state, disabled, readOnly }), children: [ /* @__PURE__ */ (0, import_jsx_runtime12.jsx)("span", { className: "gap-md flex items-center justify-start", children }), /* @__PURE__ */ (0, import_jsx_runtime12.jsx)(Icon, { className: "ml-md shrink-0", size: "sm", children: /* @__PURE__ */ (0, import_jsx_runtime12.jsx)(import_ArrowHorizontalDown.ArrowHorizontalDown, {}) }), itemsComponent ] } ); }; Trigger.displayName = "Select.Trigger"; // src/select/SelectValue.tsx var import_class_variance_authority5 = require("class-variance-authority"); var import_jsx_runtime13 = require("react/jsx-runtime"); var Value = ({ children, className, placeholder: customPlaceholder, ref: forwardedRef }) => { const { selectedItem, placeholder, disabled } = useSelectContext(); const isPlaceholderSelected = selectedItem?.value == null; const valuePlaceholder = customPlaceholder || placeholder; return /* @__PURE__ */ (0, import_jsx_runtime13.jsx)( "span", { role: "presentation", "data-spark-component": "select-value", ref: forwardedRef, className: (0, import_class_variance_authority5.cx)("flex shrink items-center text-left", className), children: /* @__PURE__ */ (0, import_jsx_runtime13.jsx)( "span", { className: (0, import_class_variance_authority5.cx)( "line-clamp-1 flex-1 overflow-hidden break-all text-ellipsis", isPlaceholderSelected && !disabled && "text-on-surface/dim-1" ), children: isPlaceholderSelected ? valuePlaceholder : children || selectedItem?.text } ) } ); }; Value.displayName = "Select.Value"; // src/select/index.ts var Select2 = Object.assign(Select, { Group, Item, Items, Placeholder, Label, Trigger, Value, LeadingIcon }); Select2.displayName = "Select"; Group.displayName = "Select.Group"; Items.displayName = "Select.Items"; Item.displayName = "Select.Item"; Placeholder.displayName = "Select.Placeholder"; Label.displayName = "Select.Label"; Trigger.displayName = "Select.Trigger"; Value.displayName = "Select.Value"; LeadingIcon.displayName = "Select.LeadingIcon"; // Annotate the CommonJS export names for ESM import in node: 0 && (module.exports = { Select, SelectProvider, useSelectContext }); //# sourceMappingURL=index.js.map