UNPKG

@wikimedia/codex

Version:

Codex Design System for Wikimedia

1,570 lines 404 kB
var __defProp = Object.defineProperty; var __defProps = Object.defineProperties; var __getOwnPropDescs = Object.getOwnPropertyDescriptors; var __getOwnPropSymbols = Object.getOwnPropertySymbols; var __hasOwnProp = Object.prototype.hasOwnProperty; var __propIsEnum = Object.prototype.propertyIsEnumerable; var __defNormalProp = (obj, key, value) => key in obj ? __defProp(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value; var __spreadValues = (a, b) => { for (var prop in b || (b = {})) if (__hasOwnProp.call(b, prop)) __defNormalProp(a, prop, b[prop]); if (__getOwnPropSymbols) for (var prop of __getOwnPropSymbols(b)) { if (__propIsEnum.call(b, prop)) __defNormalProp(a, prop, b[prop]); } return a; }; var __spreadProps = (a, b) => __defProps(a, __getOwnPropDescs(b)); var __objRest = (source, exclude) => { var target = {}; for (var prop in source) if (__hasOwnProp.call(source, prop) && exclude.indexOf(prop) < 0) target[prop] = source[prop]; if (source != null && __getOwnPropSymbols) for (var prop of __getOwnPropSymbols(source)) { if (exclude.indexOf(prop) < 0 && __propIsEnum.call(source, prop)) target[prop] = source[prop]; } return target; }; var __publicField = (obj, key, value) => __defNormalProp(obj, typeof key !== "symbol" ? key + "" : key, value); import { ref, onMounted, defineComponent, computed, createElementBlock, openBlock, normalizeClass, createCommentVNode, toDisplayString, Comment, warn, watch, withKeys, withModifiers, renderSlot, toRef, resolveComponent, createElementVNode, createBlock, resolveDynamicComponent, withCtx, createVNode, Fragment, renderList, createTextVNode, Transition, normalizeStyle, inject, mergeProps, useId, withDirectives, vModelCheckbox, createSlots, unref, shallowRef, getCurrentScope, onScopeDispose, shallowReadonly, resolveDirective, nextTick, vModelDynamic, onUnmounted, Teleport, toHandlers, vShow, provide, toRefs, reactive, vModelRadio, vModelText, getCurrentInstance } from "vue"; const g = '<path d="M11.53 2.3A1.85 1.85 0 0010 1.21 1.85 1.85 0 008.48 2.3L.36 16.36C-.48 17.81.21 19 1.88 19h16.24c1.67 0 2.36-1.19 1.52-2.64zM11 16H9v-2h2zm0-4H9V6h2z"/>', w = '<path d="M12.43 14.34A5 5 0 0110 15a5 5 0 113.95-2L17 16.09V3a2 2 0 00-2-2H5a2 2 0 00-2 2v14a2 2 0 002 2h10a2 2 0 001.45-.63z"/><circle cx="10" cy="10" r="3"/>', v1 = '<path d="M7 14.17 2.83 10l-1.41 1.41L7 17 19 5l-1.41-1.42z"/>', e1 = '<path d="M10 0a10 10 0 1010 10A10 10 0 0010 0m5.66 14.24-1.41 1.41L10 11.41l-4.24 4.25-1.42-1.42L8.59 10 4.34 5.76l1.42-1.42L10 8.59l4.24-4.24 1.41 1.41L11.41 10z"/>', z1 = '<path d="m4.34 2.93 12.73 12.73-1.41 1.41L2.93 4.35z"/><path d="M17.07 4.34 4.34 17.07l-1.41-1.41L15.66 2.93z"/>', L1 = '<path d="M10 15 2 5h16z"/>', S1 = '<path d="M13.728 1H6.272L1 6.272v7.456L6.272 19h7.456L19 13.728V6.272zM11 15H9v-2h2zm0-4H9V5h2z"/>', q1 = '<path d="m17.5 4.75-7.5 7.5-7.5-7.5L1 6.25l9 9 9-9z"/>', $1 = '<path d="M2 2a2 2 0 00-2 2v12a2 2 0 002 2h16a2 2 0 002-2V4a2 2 0 00-2-2zm-.17 13 4.09-5.25 2.92 3.51L12.92 8l5.25 7z"/>', l0 = '<path d="M19 3H1v14h18zM3 14l3.5-4.5 2.5 3L12.5 8l4.5 6z"/><path d="M19 5H1V3h18zm0 12H1v-2h18z"/>', i = '<path d="M8 19a1 1 0 001 1h2a1 1 0 001-1v-1H8zm9-12a7 7 0 10-12 4.9S7 14 7 15v1a1 1 0 001 1h4a1 1 0 001-1v-1c0-1 2-3.1 2-3.1A7 7 0 0017 7"/>', p0 = '<path d="M10 0C4.477 0 0 4.477 0 10s4.477 10 10 10 10-4.477 10-10S15.523 0 10 0M9 5h2v2H9zm0 4h2v6H9z"/>', H2 = '<path d="M3 1h2v18H3zm13.5 1.5L15 1l-9 9 9 9 1.5-1.5L9 10z"/>', x2 = '<path d="M15 1h2v18h-2zM3.5 2.5 11 10l-7.5 7.5L5 19l9-9-9-9z"/>', C2 = '<path d="M7 1 5.6 2.5 13 10l-7.4 7.5L7 19l9-9z"/>', W2 = '<path d="m4 10 9 9 1.4-1.5L7 10l7.4-7.5L13 1z"/>', t5 = '<path d="M12.2 13.6a7 7 0 111.4-1.4l5.4 5.4-1.4 1.4zM3 8a5 5 0 1010 0A5 5 0 003 8"/>', r5 = '<path d="M10 0 3 8h14zm0 18-7-8h14z"/>', I5 = '<path d="M10 20a10 10 0 010-20 10 10 0 110 20m-2-5 9-8.5L15.5 5 8 12 4.5 8.5 3 10z"/>', c3 = '<path d="m10 5 8 10H2z"/>', C3 = g, P3 = w, l4 = v1, v4 = e1, e4 = z1, V4 = L1, F4 = S1, f4 = q1, j4 = $1, t6 = l0, e6 = { langCodeMap: { ar: i }, default: p0 }, s7 = { ltr: H2, shouldFlip: true }, l7 = { ltr: x2, shouldFlip: true }, i7 = { ltr: C2, shouldFlip: true }, k7 = { ltr: W2, shouldFlip: true }, E7 = t5, j7 = r5, n8 = I5, U8 = c3; function n9(c, s, o) { if (typeof c == "string" || "path" in c) return c; if ("shouldFlip" in c) return c.ltr; if ("rtl" in c) return o === "rtl" ? c.rtl : c.ltr; const v = s in c.langCodeMap ? c.langCodeMap[s] : c.default; return typeof v == "string" || "path" in v ? v : v.ltr; } function v9(c, s) { if (typeof c == "string") return false; if ("langCodeMap" in c) { const o = s in c.langCodeMap ? c.langCodeMap[s] : c.default; if (typeof o == "string") return false; c = o; } if ("shouldFlipExceptions" in c && Array.isArray(c.shouldFlipExceptions)) { const o = c.shouldFlipExceptions.indexOf(s); return o === void 0 || o === -1; } return "shouldFlip" in c ? c.shouldFlip : false; } function useComputedDirection(root) { const computedDir = ref(null); onMounted(() => { const dir = window.getComputedStyle(root.value).direction; computedDir.value = dir === "ltr" || dir === "rtl" ? dir : null; }); return computedDir; } function useComputedLanguage(root) { const computedLang = ref(""); onMounted(() => { let ancestor = root.value; while (ancestor && ancestor.lang === "") { ancestor = ancestor.parentElement; } computedLang.value = ancestor ? ancestor.lang : null; }); return computedLang; } function makeStringTypeValidator(allowedValues) { return (s) => typeof s === "string" && allowedValues.includes(s); } const LibraryPrefix = "cdx"; const ButtonActions = [ "default", "progressive", "destructive" ]; const ButtonWeights = [ "normal", "primary", "quiet" ]; const ButtonSizes = [ "small", "medium", "large" ]; const IconSizes = [ "x-small", "small", "medium" ]; const StatusTypes = [ "notice", "warning", "error", "success" ]; const statusTypeValidator = makeStringTypeValidator(StatusTypes); const TextInputTypes = [ "text", "search", "number", "email", "month", "password", "tel", "url", "week", "date", "datetime-local", "time" ]; const ValidationStatusTypes = [ "default", "warning", "error", "success" ]; const TableTextAlignments = [ "start", "center", "end", // Numbers should be aligned to the right in all reading directionalities. "number" ]; const ImageAspectRatios = [ "16:9", "3:2", "4:3", "1:1", "3:4", "2:3" ]; const imageAspectRatioValidator = makeStringTypeValidator(ImageAspectRatios); const ObjectFitOptions = [ "fill", "contain", "cover", "none", "scale-down" ]; const objectFitValidator = makeStringTypeValidator(ObjectFitOptions); const ObjectPositions = [ "top", "bottom", "left", "right", "center" ]; const imagePositionValidator = makeStringTypeValidator(ObjectPositions); const AccordionSeparations = [ "none", "minimal", "divider", "outline" ]; const DebounceInterval = 120; const PendingDelay = 500; const MenuFooterValue = "cdx-menu-footer-item"; const TabsKey = Symbol("CdxTabs"); const ActiveTabKey = Symbol("CdxActiveTab"); const AllowArbitraryKey = Symbol("CdxAllowArbitrary"); const FieldInputIdKey = Symbol("CdxFieldInputId"); const FieldDescriptionIdKey = Symbol("CdxFieldDescriptionId"); const FieldStatusKey = Symbol("CdxFieldStatus"); const DisabledKey = Symbol("CdxDisabled"); const NoInvertClass = "".concat(LibraryPrefix, "-no-invert"); const TableRowIdentifier = Symbol("CdxTableRowIdentifier"); const TablePaginationPositions = [ "top", "bottom", "both" ]; const oppositeSides = { left: "right", "left-start": "right", "left-end": "right", top: "bottom", "top-start": "bottom", "top-end": "bottom", bottom: "top", "bottom-start": "top", "bottom-end": "top", right: "left", "right-start": "left", "right-end": "left" }; const iconSizeValidator = makeStringTypeValidator(IconSizes); const _sfc_main$B = defineComponent({ name: "CdxIcon", props: { /** The SVG path or an object containing that path plus other data. */ icon: { type: [String, Object], required: true }, /** * Accessible label for the icon. If not included, the icon will be hidden from screen * readers via `aria-hidden="true"`. Browsers also display this label as a tooltip when the * user hovers over the icon. Note that this label is not rendered as visible text next * to the icon. */ iconLabel: { type: String, default: "" }, /** * Explicitly set the language code to use for the icon. See * https://developer.mozilla.org/en-US/docs/Web/API/HTMLElement/lang. * Defaults to the lang attribute of the nearest ancestor at mount time. */ lang: { type: String, default: null }, /** * Explicitly set the direction to use for the icon. See * https://developer.mozilla.org/en-US/docs/Web/API/HTMLElement/dir. * Defaults to the computed direction at mount time. */ dir: { type: String, default: null }, /** * Specify icon size by choosing one of several pre-defined size * options. See the type documentation for supported size options. * The `medium` size is used by default if no size prop is provided. */ size: { type: String, default: "medium", validator: iconSizeValidator } }, setup(props) { const rootElement = ref(); const computedDir = useComputedDirection(rootElement); const computedLang = useComputedLanguage(rootElement); const overriddenDir = computed(() => { var _a; return (_a = props.dir) != null ? _a : computedDir.value; }); const overriddenLang = computed(() => { var _a; return (_a = props.lang) != null ? _a : computedLang.value; }); const rootClasses = computed(() => ({ "cdx-icon--flipped": overriddenDir.value === "rtl" && overriddenLang.value !== null && v9(props.icon, overriddenLang.value), ["cdx-icon--".concat(props.size)]: true })); const resolvedIcon = computed( () => { var _a, _b; return n9(props.icon, (_a = overriddenLang.value) != null ? _a : "", (_b = overriddenDir.value) != null ? _b : "ltr"); } ); const iconSvg = computed(() => typeof resolvedIcon.value === "string" ? resolvedIcon.value : ""); const iconPath = computed(() => typeof resolvedIcon.value !== "string" ? resolvedIcon.value.path : ""); return { rootElement, rootClasses, iconSvg, iconPath }; } }); const _export_sfc = (sfc, props) => { const target = sfc.__vccOpts || sfc; for (const [key, val] of props) { target[key] = val; } return target; }; const _hoisted_1$y = ["aria-hidden"]; const _hoisted_2$l = { key: 0 }; const _hoisted_3$e = ["innerHTML"]; const _hoisted_4$b = ["d"]; function _sfc_render$B(_ctx, _cache, $props, $setup, $data, $options) { return openBlock(), createElementBlock( "span", { ref: "rootElement", class: normalizeClass(["cdx-icon", _ctx.rootClasses]) }, [ (openBlock(), createElementBlock("svg", { xmlns: "http://www.w3.org/2000/svg", width: "20", height: "20", viewBox: "0 0 20 20", "aria-hidden": _ctx.iconLabel ? void 0 : true }, [ _ctx.iconLabel ? (openBlock(), createElementBlock( "title", _hoisted_2$l, toDisplayString(_ctx.iconLabel), 1 /* TEXT */ )) : createCommentVNode("v-if", true), _ctx.iconSvg ? (openBlock(), createElementBlock("g", { key: 1, innerHTML: _ctx.iconSvg }, null, 8, _hoisted_3$e)) : (openBlock(), createElementBlock("path", { key: 2, d: _ctx.iconPath }, null, 8, _hoisted_4$b)) ], 8, _hoisted_1$y)) ], 2 /* CLASS */ ); } const CdxIcon = /* @__PURE__ */ _export_sfc(_sfc_main$B, [["render", _sfc_render$B]]); function flattenSlotContents(slotContents) { const flattened = []; for (const node of slotContents) { if ( // HTML tag typeof node.type === "string" || // Component typeof node.type === "object" ) { flattened.push(node); } else if (node.type !== Comment) { if (typeof node.children === "string" && node.children.trim() !== "") { flattened.push(node.children); } else if (Array.isArray(node.children)) { flattened.push(...flattenSlotContents(node.children)); } } } return flattened; } function isComponentVNode(node, componentName) { if (typeof node.type === "object" && "name" in node.type) { if (componentName !== void 0) { return node.type.name === componentName; } return true; } return false; } function isTagVNode(node, tagName) { if (typeof node.type === "string") { { return node.type === tagName.toLowerCase(); } } return false; } function useSlotContents(slot) { const slotContents = typeof slot === "function" ? slot() : slot; return slotContents ? flattenSlotContents(slotContents) : []; } function useWarnOnce(shouldWarn, message) { if (shouldWarn()) { warn(message); return; } const stop = watch(shouldWarn, (newValue) => { if (newValue) { warn(message); stop(); } }); } function useIconOnlyButton(slot, attrs, componentName) { const isIconOnly = computed(() => { const slotContents = useSlotContents(slot); if (slotContents.length !== 1) { return false; } const soleNode = slotContents[0]; if (typeof soleNode === "object" && (isComponentVNode(soleNode, "CdxIcon") || isTagVNode(soleNode, "svg"))) { return true; } return false; }); useWarnOnce( () => isIconOnly.value && !attrs["aria-label"] && !attrs["aria-hidden"], "".concat(componentName, ": Icon-only buttons require one of the following attributes: aria-label or aria-hidden. See documentation at https://doc.wikimedia.org/codex/latest/components/demos/button.html#icon-only-button") ); return isIconOnly; } const buttonActionValidator = makeStringTypeValidator(ButtonActions); const buttonWeightValidator = makeStringTypeValidator(ButtonWeights); const buttonSizeValidator = makeStringTypeValidator(ButtonSizes); const _sfc_main$A = defineComponent({ name: "CdxButton", props: { /** * The kind of action that will be taken on click. * * @values 'default', 'progressive', 'destructive' */ action: { type: String, default: "default", validator: buttonActionValidator }, /** * Visual prominence of Button. * * @values 'normal', 'primary', 'quiet' */ weight: { type: String, default: "normal", validator: buttonWeightValidator }, /** * Button size. * * Medium: Default for most cases. * Large: Use rarely, mainly for icon-only buttons on touchscreens. * Small: Use in tight spaces or inline with text. * Avoid on touchscreens - prefer medium for better accessibility. * * @values 'small', 'medium', 'large' */ size: { type: String, default: "medium", validator: buttonSizeValidator } }, emits: ["click"], setup(props, { emit, slots, attrs }) { const button = ref(); const isIconOnly = useIconOnlyButton(slots.default, attrs, "CdxButton"); const isActive = ref(false); const rootClasses = computed(() => ({ ["cdx-button--action-".concat(props.action)]: true, ["cdx-button--weight-".concat(props.weight)]: true, ["cdx-button--size-".concat(props.size)]: true, "cdx-button--framed": props.weight !== "quiet", "cdx-button--icon-only": isIconOnly.value, "cdx-button--is-active": isActive.value })); const onClick = (event) => { emit("click", event); }; const setActive = (active) => { isActive.value = active; }; function onKeyDown() { setActive(true); } function onKeyUp() { var _a; setActive(false); (_a = button.value) == null ? void 0 : _a.click(); } return { button, rootClasses, onClick, onKeyDown, onKeyUp }; } }); function _sfc_render$A(_ctx, _cache, $props, $setup, $data, $options) { return openBlock(), createElementBlock( "button", { ref: "button", class: normalizeClass(["cdx-button", _ctx.rootClasses]), onKeydown: _cache[0] || (_cache[0] = withKeys(withModifiers((...args) => _ctx.onKeyDown && _ctx.onKeyDown(...args), ["prevent"]), ["space", "enter"])), onKeyup: _cache[1] || (_cache[1] = withKeys((...args) => _ctx.onKeyUp && _ctx.onKeyUp(...args), ["space", "enter"])), onClick: _cache[2] || (_cache[2] = (...args) => _ctx.onClick && _ctx.onClick(...args)) }, [ renderSlot(_ctx.$slots, "default") ], 34 /* CLASS, NEED_HYDRATION */ ); } const CdxButton = /* @__PURE__ */ _export_sfc(_sfc_main$A, [["render", _sfc_render$A]]); function useOptionalModelWrapper(internalValueRef, modelValueRef, emit, eventName) { return computed({ get: () => { var _a; return (_a = modelValueRef.value) != null ? _a : internalValueRef.value; }, set: (value) => { if (modelValueRef.value !== null) { emit(eventName || "update:modelValue", value); } else { internalValueRef.value = value; } } }); } const separationValidator = makeStringTypeValidator(AccordionSeparations); const _sfc_main$z = defineComponent({ name: "CdxAccordion", components: { CdxButton, CdxIcon }, props: { /** * This component accepts an optional v-model binding; use it if you * want to programmatically control the Accordion's open/closed state. * If this feature is not needed, you can omit `v-model` and just use * the "open" attribute if you want the component to render in the * expanded state. */ modelValue: { type: [Boolean, null], default: null }, /** * Forces the accordion to show the action icon. */ actionAlwaysVisible: { type: Boolean, default: false }, /** * Sets the visual style and sometimes size of the accordion. * * - 'none': no divider or outline, size scales with header content. * - 'minimal': no divider or outline, fixed small size. * - 'divider': divider line between mmultiple accordions, size scales with header content. * - 'outline': border around entire accordion, size scales with header content. * * @values 'none', 'minimal', 'divider', 'outline' */ separation: { type: String, default: "divider", validator: separationValidator }, /** * The icon that will be displayed on the right side of the accordion header when expanded. * */ actionIcon: { type: [String, Object], default: null }, /** * Label for the action button. If an action icon is being used, then a label for that icon * should be provided for ARIA support. */ actionButtonLabel: { type: String, default: "" }, /** * The heading level of the accordion title. * * @values 'h1', 'h2', 'h3', 'h4', 'h5', 'h6' */ headingLevel: { type: String, default: "h3" } }, emits: [ /** * When the action button is clicked. * */ "action-button-click", /** * When the "open" state changes. Only emitted if v-model binding * is used in the parent scope. * * @param {boolean} newVal */ "update:modelValue", /** * When the Accordion is toggled open or closed. Always emitted * regardless of v-model binding. * * @param {boolean} isOpen */ "toggle" ], setup(props, { attrs, emit }) { const internalOpen = ref("open" in attrs); const computedOpen = useOptionalModelWrapper( internalOpen, toRef(props, "modelValue"), emit ); const emitActionButtonClick = () => { emit("action-button-click"); }; const onToggle = (e) => { computedOpen.value = e.newState === "open"; emit("toggle", computedOpen.value); }; const shouldShowActionButton = computed(() => { if (props.actionIcon) { if (computedOpen.value) { return true; } else if (props.actionAlwaysVisible) { return true; } else { return false; } } else { return false; } }); const rootClasses = computed(() => ({ "cdx-accordion--has-icon": shouldShowActionButton.value, ["cdx-accordion--separation-".concat(props.separation)]: true })); return { emitActionButtonClick, rootClasses, shouldShowActionButton, onToggle, computedOpen }; } }); const _hoisted_1$x = ["open"]; const _hoisted_2$k = { class: "cdx-accordion__header__title" }; const _hoisted_3$d = { class: "cdx-accordion__header__description" }; function _sfc_render$z(_ctx, _cache, $props, $setup, $data, $options) { const _component_cdx_icon = resolveComponent("cdx-icon"); const _component_cdx_button = resolveComponent("cdx-button"); return openBlock(), createElementBlock("details", { class: normalizeClass(["cdx-accordion", _ctx.rootClasses]), open: _ctx.computedOpen || void 0, onToggle: _cache[1] || (_cache[1] = (...args) => _ctx.onToggle && _ctx.onToggle(...args)) }, [ createElementVNode("summary", null, [ (openBlock(), createBlock(resolveDynamicComponent(_ctx.headingLevel), { class: "cdx-accordion__header" }, { default: withCtx(() => [ createElementVNode("span", _hoisted_2$k, [ renderSlot(_ctx.$slots, "title") ]), createElementVNode("span", _hoisted_3$d, [ renderSlot(_ctx.$slots, "description") ]) ]), _: 3 /* FORWARDED */ })), _ctx.shouldShowActionButton ? (openBlock(), createBlock(_component_cdx_button, { key: 0, class: "cdx-accordion__action", "aria-label": _ctx.actionButtonLabel, type: "button", weight: "quiet", onClick: withModifiers(_ctx.emitActionButtonClick, ["stop"]) }, { default: withCtx(() => [ createVNode(_component_cdx_icon, { icon: _ctx.actionIcon, "icon-label": _ctx.actionButtonLabel, size: "medium" }, null, 8, ["icon", "icon-label"]) ]), _: 1 /* STABLE */ }, 8, ["aria-label", "onClick"])) : createCommentVNode("v-if", true) ]), createElementVNode("div", { class: "cdx-accordion__content", onClick: _cache[0] || (_cache[0] = withModifiers(() => { }, ["stop"])) }, [ renderSlot(_ctx.$slots, "default") ]) ], 42, _hoisted_1$x); } const Accordion = /* @__PURE__ */ _export_sfc(_sfc_main$z, [["render", _sfc_render$z]]); function getButtonLabel(button) { if (button.label === void 0) { return button.value; } if (button.label === null) { return ""; } return button.label; } function useButtonGroupKeyboardNav(buttonsProp) { const rootElement = ref(); const focusedButtonIndex = ref(); const buttonRefs = ref(/* @__PURE__ */ new Map()); const currentDirection = useComputedDirection(rootElement); function assignTemplateRef(templateRef, index) { const button = templateRef; if (button) { buttonRefs.value.set(index, button); } } function onFocus(index) { focusedButtonIndex.value = index; } function onBlur() { focusedButtonIndex.value = void 0; } function focusNonDisabled(index, increment) { var _a; const newIndex = index + increment; const targetButton = buttonsProp.value[newIndex]; if (targetButton) { if (targetButton.disabled) { focusNonDisabled(newIndex, increment); } else { const buttonElement = (_a = buttonRefs.value.get(newIndex)) == null ? void 0 : _a.$el; buttonElement == null ? void 0 : buttonElement.focus(); } } } function next() { var _a; focusNonDisabled((_a = focusedButtonIndex.value) != null ? _a : -1, 1); } function prev() { var _a; focusNonDisabled((_a = focusedButtonIndex.value) != null ? _a : buttonsProp.value.length, -1); } function moveRight() { if (currentDirection.value === "rtl") { prev(); } else { next(); } } function moveLeft() { if (currentDirection.value === "rtl") { next(); } else { prev(); } } function onKeydown(e) { switch (e.key) { case "ArrowRight": e.preventDefault(); moveRight(); break; case "ArrowLeft": e.preventDefault(); moveLeft(); break; case "ArrowDown": e.preventDefault(); next(); break; case "ArrowUp": e.preventDefault(); prev(); break; } } return { rootElement, assignTemplateRef, onFocus, onBlur, onKeydown }; } const _sfc_main$y = defineComponent({ name: "CdxButtonGroup", components: { CdxButton, CdxIcon }, props: { /** * Objects describing the buttons in the group. See the ButtonGroupItem type. */ buttons: { type: Array, required: true, validator: (value) => Array.isArray(value) && value.length >= 1 }, /** * Whether the entire group is disabled. * * If this is set to true, all buttons in the group are disabled. Buttons can also be * disabled individually by setting their `disabled` property to true. */ disabled: { type: Boolean, default: false } }, emits: [ /** * Emitted when a button is clicked * * @property {string | number} value The `value` property of the button that was clicked */ "click" ], setup(props) { const { rootElement, assignTemplateRef, onFocus, onBlur, onKeydown } = useButtonGroupKeyboardNav(toRef(props, "buttons")); return { rootElement, assignTemplateRef, onFocus, onBlur, onKeydown, getButtonLabel }; } }); const _hoisted_1$w = { ref: "rootElement", class: "cdx-button-group" }; function _sfc_render$y(_ctx, _cache, $props, $setup, $data, $options) { const _component_cdx_icon = resolveComponent("cdx-icon"); const _component_cdx_button = resolveComponent("cdx-button"); return openBlock(), createElementBlock( "div", _hoisted_1$w, [ (openBlock(true), createElementBlock( Fragment, null, renderList(_ctx.buttons, (button, index) => { return openBlock(), createBlock(_component_cdx_button, { key: button.value, ref_for: true, ref: (ref2) => _ctx.assignTemplateRef(ref2, index), disabled: button.disabled || _ctx.disabled, "aria-label": button.ariaLabel, onClick: ($event) => _ctx.$emit("click", button.value), onFocus: ($event) => _ctx.onFocus(index), onBlur: _ctx.onBlur, onKeydown: _ctx.onKeydown }, { default: withCtx(() => [ renderSlot(_ctx.$slots, "default", { button }, () => [ button.icon ? (openBlock(), createBlock(_component_cdx_icon, { key: 0, icon: button.icon }, null, 8, ["icon"])) : createCommentVNode("v-if", true), createTextVNode( " " + toDisplayString(_ctx.getButtonLabel(button)), 1 /* TEXT */ ) ]) ]), _: 2 /* DYNAMIC */ }, 1032, ["disabled", "aria-label", "onClick", "onFocus", "onBlur", "onKeydown"]); }), 128 /* KEYED_FRAGMENT */ )) ], 512 /* NEED_PATCH */ ); } const ButtonGroup = /* @__PURE__ */ _export_sfc(_sfc_main$y, [["render", _sfc_render$y]]); const _sfc_main$x = defineComponent({ name: "CdxThumbnail", components: { CdxIcon }, props: { /** * Thumbnail data. */ thumbnail: { type: [Object, null], default: null }, /** * Thumbnail placeholder icon. */ placeholderIcon: { type: [String, Object], default: t6 } }, setup: (props) => { const thumbnailLoaded = ref(false); const thumbnailStyle = ref({}); const preloadThumbnail = (url) => { const escapedUrl = url.replace(/([\\"\n])/g, "\\$1"); const image = new Image(); image.onload = () => { thumbnailStyle.value = { backgroundImage: 'url("'.concat(escapedUrl, '")') }; thumbnailLoaded.value = true; }; image.onerror = () => { thumbnailLoaded.value = false; }; image.src = escapedUrl; }; onMounted(() => { var _a; if ((_a = props.thumbnail) == null ? void 0 : _a.url) { preloadThumbnail(props.thumbnail.url); } }); watch(toRef(props, "thumbnail"), (newThumbnail, oldThumbnail) => { if (!(newThumbnail == null ? void 0 : newThumbnail.url)) { thumbnailLoaded.value = false; thumbnailStyle.value = {}; return; } if ((oldThumbnail == null ? void 0 : oldThumbnail.url) !== newThumbnail.url) { thumbnailLoaded.value = false; preloadThumbnail(newThumbnail.url); } }, { deep: true }); return { thumbnailStyle, thumbnailLoaded, NoInvertClass }; } }); const _hoisted_1$v = { class: "cdx-thumbnail" }; const _hoisted_2$j = { key: 0, class: "cdx-thumbnail__placeholder" }; function _sfc_render$x(_ctx, _cache, $props, $setup, $data, $options) { const _component_cdx_icon = resolveComponent("cdx-icon"); return openBlock(), createElementBlock("span", _hoisted_1$v, [ !_ctx.thumbnailLoaded ? (openBlock(), createElementBlock("span", _hoisted_2$j, [ createVNode(_component_cdx_icon, { icon: _ctx.placeholderIcon, class: "cdx-thumbnail__placeholder__icon--vue" }, null, 8, ["icon"]) ])) : createCommentVNode("v-if", true), createVNode(Transition, { name: "cdx-thumbnail__image" }, { default: withCtx(() => [ _ctx.thumbnailLoaded ? (openBlock(), createElementBlock( "span", { key: 0, style: normalizeStyle(_ctx.thumbnailStyle), class: normalizeClass([_ctx.NoInvertClass, "cdx-thumbnail__image"]) }, null, 6 /* CLASS, STYLE */ )) : createCommentVNode("v-if", true) ]), _: 1 /* STABLE */ }) ]); } const CdxThumbnail = /* @__PURE__ */ _export_sfc(_sfc_main$x, [["render", _sfc_render$x]]); const _sfc_main$w = defineComponent({ name: "CdxCard", components: { CdxIcon, CdxThumbnail }, props: { /** * If provided, the Card will be a link to this URL. */ url: { type: String, default: "" }, /** * Icon displayed at the start of the Card. */ icon: { type: [String, Object], default: "" }, /** * Thumbnail image data for the Card. */ thumbnail: { type: [Object, null], default: null }, /** * Option to force a thumbnail layout. * * When set to `true`, the Card will display a Thumbnail. If a `thumbnail` prop was also * provided, the thumbnail image will display. Otherwise, a placeholder icon will display. * * This is useful when displaying groups of Cards when some of the cards have thumbnail * images but some do not. `forceThumbnail` will provide a consistent layout for that group. * * Note that this prop is not needed to display a thumbnail image: if the `thumbnail` prop * is provided, it will display. This prop is only needed to enable the display of the * thumbnail placeholder icon when the `thumbnail` prop is not provided. */ forceThumbnail: { type: Boolean, default: false }, /** * Optional custom icon for the placeholder shown when `forceThumbnail` is true but no * thumbnail is provided. * * Defaults to the default placeholder icon set in the Thumbnail component. */ customPlaceholderIcon: { type: [String, Object], default: void 0 } }, setup(props) { const isLink = computed(() => !!props.url); const contentTag = computed(() => isLink.value ? "a" : "span"); const cardLink = computed(() => isLink.value ? props.url : void 0); return { isLink, contentTag, cardLink }; } }); const _hoisted_1$u = { class: "cdx-card__text" }; const _hoisted_2$i = { class: "cdx-card__text__title" }; const _hoisted_3$c = { key: 0, class: "cdx-card__text__description" }; const _hoisted_4$a = { key: 1, class: "cdx-card__text__supporting-text" }; function _sfc_render$w(_ctx, _cache, $props, $setup, $data, $options) { const _component_cdx_thumbnail = resolveComponent("cdx-thumbnail"); const _component_cdx_icon = resolveComponent("cdx-icon"); return openBlock(), createBlock(resolveDynamicComponent(_ctx.contentTag), { href: _ctx.cardLink, class: normalizeClass(["cdx-card", { "cdx-card--is-link": _ctx.isLink, // Include dynamic classes in the template so that $slots is reactive. "cdx-card--title-only": !_ctx.$slots.description && !_ctx.$slots["supporting-text"] }]) }, { default: withCtx(() => [ _ctx.thumbnail || _ctx.forceThumbnail ? (openBlock(), createBlock(_component_cdx_thumbnail, { key: 0, thumbnail: _ctx.thumbnail, "placeholder-icon": _ctx.customPlaceholderIcon, class: "cdx-card__thumbnail" }, null, 8, ["thumbnail", "placeholder-icon"])) : _ctx.icon ? (openBlock(), createBlock(_component_cdx_icon, { key: 1, icon: _ctx.icon, class: "cdx-card__icon" }, null, 8, ["icon"])) : createCommentVNode("v-if", true), createElementVNode("span", _hoisted_1$u, [ createElementVNode("span", _hoisted_2$i, [ renderSlot(_ctx.$slots, "title") ]), _ctx.$slots.description ? (openBlock(), createElementBlock("span", _hoisted_3$c, [ renderSlot(_ctx.$slots, "description") ])) : createCommentVNode("v-if", true), _ctx.$slots["supporting-text"] ? (openBlock(), createElementBlock("span", _hoisted_4$a, [ renderSlot(_ctx.$slots, "supporting-text") ])) : createCommentVNode("v-if", true) ]) ]), _: 3 /* FORWARDED */ }, 8, ["href", "class"]); } const Card = /* @__PURE__ */ _export_sfc(_sfc_main$w, [["render", _sfc_render$w]]); function useComputedDisabled(disabledProp) { const providedDisabled = inject(DisabledKey, ref(false)); return computed(() => providedDisabled.value || disabledProp.value); } function useFieldData(disabledProp, statusProp, idAttr) { const computedDisabled = useComputedDisabled(disabledProp); const providedStatus = inject(FieldStatusKey, ref("default")); const computedStatus = computed(() => { if ((statusProp == null ? void 0 : statusProp.value) && statusProp.value !== "default") { return statusProp.value; } return providedStatus.value; }); const providedId = inject(FieldInputIdKey, void 0); const computedInputId = computed(() => { var _a; return (_a = providedId == null ? void 0 : providedId.value) != null ? _a : idAttr; }); return { computedDisabled, computedStatus, computedInputId }; } function useSplitAttributes(attrs, internalClasses = computed(() => ({}))) { const rootClasses = computed(() => { const classRecord = __objRest(internalClasses.value, []); if (attrs.class) { const providedClasses = attrs.class.split(" "); providedClasses.forEach((className) => { classRecord[className] = true; }); } return classRecord; }); const rootStyle = computed(() => { if ("style" in attrs) { return attrs.style; } return void 0; }); const otherAttrs = computed(() => { const _a = attrs, { class: _ignoredClass, style: _ignoredStyle } = _a, attrsCopy = __objRest(_a, ["class", "style"]); return attrsCopy; }); return { rootClasses, rootStyle, otherAttrs }; } function useI18n(messageKey, defaultValue, params = []) { const providedI18nFunc = inject("CdxI18nFunction", void 0); return computed(() => { const unwrappedParams = params.map((p) => typeof p === "function" ? p() : p.value); const fromProvidedFunc = providedI18nFunc == null ? void 0 : providedI18nFunc(messageKey, ...unwrappedParams); if (fromProvidedFunc !== void 0 && fromProvidedFunc !== null) { return fromProvidedFunc; } return typeof defaultValue === "function" ? defaultValue(...unwrappedParams) : defaultValue; }); } function useI18nWithOverride(override, messageKey, defaultValue, params = []) { const translatedMessage = useI18n(messageKey, defaultValue, params); return computed(() => override.value || translatedMessage.value); } const _sfc_main$v = defineComponent({ name: "CdxLabel", components: { CdxIcon }, /** * We want the label or legend to inherit attributes, not the root element. */ inheritAttrs: false, props: { /** * Icon before the label text. * * Do not use this if including a start icon within the input component. */ icon: { type: [String, Object], default: null }, /** * Whether the field is optional. * * This will add a flag next to the label indicating that the field is optional. */ optional: { type: Boolean, default: false }, // DEPRECATED: set default to '(optional)' and remove validator (T368444). /** * Text to indicate that the field is optional. * * Omit this prop to use the default value, "(optional)". */ optionalFlag: { type: String, default: "", validator: (value, props) => { if (value.length > 0 && !props.optional) { console.warn( "[CdxLabel]: The boolean `optional` prop is required to show the optional flag.\n\nRefer to https://doc.wikimedia.org/codex/latest/components/demos/label.html#props." ); return false; } return true; } }, /** * Whether the label should be visually hidden. */ visuallyHidden: { type: Boolean, default: false }, /** * Whether this component should output a `<legend>` element. * * Always set this to true when this component is used inside a `<fieldset>` element. Do not * set it to true otherwise. */ isLegend: { type: Boolean, default: false }, /** * The ID of the input/control this label is for. * * Will be added as the `for` attribute of the `<label>`. Not needed for `<legend>`. */ inputId: { type: String, default: "" }, /** * The ID of the description element. * * This ID can be used for the `aria-describedby` attribute of the input. */ descriptionId: { type: String, default: "" }, /** * Whether this label is for a disabled field or input. */ disabled: { type: Boolean, default: false } }, setup(props, { attrs }) { const { computedDisabled } = useFieldData(toRef(props, "disabled")); const internalClasses = computed(() => ({ "cdx-label--visually-hidden": props.visuallyHidden, "cdx-label--disabled": computedDisabled.value })); const { rootClasses, rootStyle, otherAttrs } = useSplitAttributes(attrs, internalClasses); const translatedOptionalFlag = useI18nWithOverride( toRef(props, "optionalFlag"), "cdx-label-optional-flag", "(optional)" ); return { rootClasses, rootStyle, otherAttrs, translatedOptionalFlag }; } }); const _hoisted_1$t = ["for"]; const _hoisted_2$h = { class: "cdx-label__label__text" }; const _hoisted_3$b = { key: 1, class: "cdx-label__label__optional-flag" }; const _hoisted_4$9 = ["id"]; const _hoisted_5$9 = { class: "cdx-label__label" }; const _hoisted_6$7 = { class: "cdx-label__label__text" }; const _hoisted_7$3 = { key: 1, class: "cdx-label__label__optional-flag" }; const _hoisted_8$3 = { key: 0, class: "cdx-label__description" }; function _sfc_render$v(_ctx, _cache, $props, $setup, $data, $options) { const _component_cdx_icon = resolveComponent("cdx-icon"); return !_ctx.isLegend ? (openBlock(), createElementBlock( "div", { key: 0, class: normalizeClass(["cdx-label", _ctx.rootClasses]), style: normalizeStyle(_ctx.rootStyle) }, [ createElementVNode("label", mergeProps({ class: "cdx-label__label", for: _ctx.inputId ? _ctx.inputId : void 0 }, _ctx.otherAttrs), [ _ctx.icon ? (openBlock(), createBlock(_component_cdx_icon, { key: 0, icon: _ctx.icon, class: "cdx-label__label__icon" }, null, 8, ["icon"])) : createCommentVNode("v-if", true), createElementVNode("span", _hoisted_2$h, [ renderSlot(_ctx.$slots, "default") ]), _ctx.optionalFlag || _ctx.optional ? (openBlock(), createElementBlock( "span", _hoisted_3$b, toDisplayString(" ") + " " + toDisplayString(_ctx.translatedOptionalFlag), 1 /* TEXT */ )) : createCommentVNode("v-if", true) ], 16, _hoisted_1$t), _ctx.$slots.description && _ctx.$slots.description().length > 0 ? (openBlock(), createElementBlock("span", { key: 0, id: _ctx.descriptionId || void 0, class: "cdx-label__description" }, [ renderSlot(_ctx.$slots, "description") ], 8, _hoisted_4$9)) : createCommentVNode("v-if", true) ], 6 /* CLASS, STYLE */ )) : (openBlock(), createElementBlock( "legend", mergeProps({ key: 1, class: ["cdx-label", _ctx.rootClasses], style: _ctx.rootStyle }, _ctx.otherAttrs), [ createElementVNode("span", _hoisted_5$9, [ _ctx.icon ? (openBlock(), createBlock(_component_cdx_icon, { key: 0, icon: _ctx.icon, class: "cdx-label__label__icon" }, null, 8, ["icon"])) : createCommentVNode("v-if", true), createElementVNode("span", _hoisted_6$7, [ renderSlot(_ctx.$slots, "default") ]), _ctx.optionalFlag || _ctx.optional ? (openBlock(), createElementBlock( "span", _hoisted_7$3, toDisplayString(" ") + " " + toDisplayString(_ctx.translatedOptionalFlag), 1 /* TEXT */ )) : createCommentVNode("v-if", true) ]), _ctx.$slots.description && _ctx.$slots.description().length > 0 ? (openBlock(), createElementBlock("span", _hoisted_8$3, [ renderSlot(_ctx.$slots, "description") ])) : createCommentVNode("v-if", true) ], 16 /* FULL_PROPS */ )); } const CdxLabel = /* @__PURE__ */ _export_sfc(_sfc_main$v, [["render", _sfc_render$v]]); function useLabelChecker(slot, attrs, componentName) { useWarnOnce( () => useSlotContents(slot).length === 0 && !(attrs == null ? void 0 : attrs["aria-label"]) && !(attrs == null ? void 0 : attrs["aria-labelledby"]), "".concat(componentName, ": Inputs must have an associated label. Provide one of the following:\n - A label via the appropriate slot\n - An `aria-label` attribute set to the label text\n - An `aria-labelledby` attribute set to the ID of the label element") ); } function useModelWrapper(modelValueRef, emit, eventName) { return computed({ get: () => modelValueRef.value, // If eventName is undefined, then 'update:modelValue' must be a valid EventName, // but TypeScript's type analysis isn't clever enough to realize that set: (value) => emit(eventName || "update:modelValue", value) }); } const statusValidator$a = makeStringTypeValidator(ValidationStatusTypes); const _sfc_main$u = defineComponent({ name: "CdxCheckbox", components: { CdxLabel }, props: { /** * Value of the checkbox or checkbox group. * * Provided by `v-model` binding in the parent component. */ modelValue: { type: [Boolean, Array], default: false }, /** * HTML "value" attribute to assign to the input. * * Required for input groups. */ inputValue: { type: [String, Number, Boolean], default: false }, /** * HTML "name" attribute to assign to the input. */ name: { type: String, default: null }, /** * Whether the disabled attribute should be added to the input. */ disabled: { type: Boolean, default: false }, /** * Whether the indeterminate visual state should be displayed. * * This is unrelated to the value provided by `v-model`, and the indeterminate visual state * will override the checked or unchecked visual state. */ indeterminate: { type: Boolean, default: false }, /** * Whether the component should display inline. * * By default, `display: block` is set and a margin exists between * sibling components, for a stacked layout. */ inline: { type: Boolean, default: false }, /** * Whether the label should be visually hidden. * * When true, the label will remain accessible to assistive technology. */ hideLabel: { type: Boolean, default: false }, /** * Validation status of the Checkbox. */ status: { type: String, default: "default", validator: statusValidator$a } }, emits: [ /** * Emitted when modelValue changes. * * @property {boolean | string[] | number[]} modelValue The new model value */ "update:modelValue" ], setup(props, { emit, slots, attrs }) { var _a; useLabelChecker((_a = slots.default) == null ? void 0 : _a.call(slots), attrs, "CdxCheckbox"); const { computedDisabled, computedStatus } = useFieldData( toRef(props, "disabled"), toRef(props, "status") ); const rootClasses = computed(() => ({ "cdx-checkbox--inline": props.inline, ["cdx-checkbox--status-".concat(computedStatus.value)]: true })); const customInputClasses = computed(() => ({ "cdx-checkbox__custom-input--inline": props.inline })); const input = ref(); const checkboxId = useId(); const descriptionId = useId(); const wrappedModel = useModelWrapper(toRef(props, "modelValue"), emit); return { rootClasses, computedDisabled, input, checkboxId, descriptionId, wrappedModel, customInputClasses }; } }); const _hoisted_1$s = { class: "cdx-checkbox__wrapper" }; const _hoisted_2$g = ["id", "aria-describedby", "value", "name", "disabled", ".indeterminate"]; function _sfc_render$u(_ctx, _cache, $props, $setup, $data, $options) { const _component_cdx_label = resolveComponent("cdx-label"); return openBlock(), createElementBlock( "div", { class: normalizeClass(["cdx-checkbox", _ctx.rootClasses]) }, [ createElementVNode("div", _hoisted_1$s, [ withDirectives(createElementVNode("input", { id: _ctx.checkboxId, ref: "input", "onUpdate:modelValue": _cache[0] || (_cache[0] = ($event) => _ctx.wrappedModel = $event), class: "cdx-checkbox__input", type: "checkbox", "aria-describedby": _ctx.$slots.description && _ctx.$slots.description().length > 0 ? _ctx.descriptionId : void 0, value: _ctx.inputValue, name: _ctx.name, disabled: _ctx.computedDisabled, ".indeterminate": _ctx.indeterminate }, null, 40, _hoisted_2$g), [ [vModelCheckbox, _ctx.wrappedModel] ]), _cache[1] || (_cache[1] = createElementVNode( "span", { class: "cdx-checkbox__icon" }, null, -1 /* CACHED */ )), _ctx.$slots.default && _ctx.$slots.default().length ? (openBlock(), createBlock(_component_cdx_label, { key: 0, class: "cdx-checkbox__label", "input-id": _ctx.checkboxId, "description-id": _ctx.$slots.description && _ctx.$slots.description().length > 0 ? _ctx.descriptionId : void 0, disabled: _ctx.computedDisabled, "visually-hidden": _ctx.hideLabel }, createSlots({ default: withCtx(() => [ renderSlot(_ctx.$slots, "default") ]), _: 2 /* DYNAMIC */ }, [ _ctx.$slots.description && _ctx.$slots.description().length > 0 ? { name: "description", fn: withCtx(() => [ renderSlot(_ctx.$slots, "description") ]), key: "0" } : void 0 ]), 1032, ["input-id", "description-id", "disabled", "visually-hidden"])) : createCommentVNode("v-if", true) ]), _ctx.$slots["custom-input"] ? (openBlock(), createElementBlock( "div", { key: 0, class: normalizeClass(["cdx-checkbox__custom-input", _ctx.customInputClasses]) }, [ renderSlot(_ctx.$slots, "custom-input") ], 2 /* CLASS */ )) : createCommentVNode("v-if", true) ], 2 /* CLASS */ ); } const CdxCheckbox = /* @__PURE__ */ _export_sfc(_sfc_main$u, [["rend