@wikimedia/codex
Version:
Codex Design System for Wikimedia
1,570 lines • 400 kB
JavaScript
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);
var __async = (__this, __arguments, generator) => {
return new Promise((resolve, reject) => {
var fulfilled = (value) => {
try {
step(generator.next(value));
} catch (e) {
reject(e);
}
};
var rejected = (value) => {
try {
step(generator.throw(value));
} catch (e) {
reject(e);
}
};
var step = (x) => x.done ? resolve(x.value) : Promise.resolve(x.value).then(fulfilled, rejected);
step((generator = generator.apply(__this, __arguments)).next());
});
};
import { ref, onMounted, defineComponent, computed, openBlock, createElementBlock, normalizeClass, toDisplayString, createCommentVNode, 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, toHandlers, vShow, Teleport, toRefs, provide, 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"/>', n1 = '<path d="M7 14.17 2.83 10l-1.41 1.41L7 17 19 5l-1.41-1.42z"/>', d1 = '<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"/>', r1 = '<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"/>', u1 = '<path d="M10 15 2 5h16z"/>', f1 = '<path d="M13.728 1H6.272L1 6.272v7.456L6.272 19h7.456L19 13.728V6.272zM11 15H9v-2h2zm0-4H9V5h2z"/>', b1 = '<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"/>', s0 = '<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"/>', i0 = '<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"/>', M2 = '<path d="M3 1h2v18H3zm13.5 1.5L15 1l-9 9 9 9 1.5-1.5L9 10z"/>', g2 = '<path d="M15 1h2v18h-2zM3.5 2.5 11 10l-7.5 7.5L5 19l9-9-9-9z"/>', A2 = '<path d="M7 1 5.6 2.5 13 10l-7.4 7.5L7 19l9-9z"/>', Z2 = '<path d="m4 10 9 9 1.4-1.5L7 10l7.4-7.5L13 1z"/>', c5 = '<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"/>', d5 = '<path d="M10 0 3 8h14zm0 18-7-8h14z"/>', u5 = '<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"/>', X5 = '<path d="m10 5 8 10H2z"/>', I3 = g, R3 = w, t4 = n1, o4 = d1, l4 = r1, M4 = u1, I4 = f1, C4 = b1, G4 = _1, _4 = s0, l6 = {
langCodeMap: {
ar: i
},
default: i0
}, c7 = {
ltr: M2,
shouldFlip: true
}, a7 = {
ltr: g2,
shouldFlip: true
}, v7 = {
ltr: A2,
shouldFlip: true
}, V7 = {
ltr: Z2,
shouldFlip: true
}, Z7 = c5, Q7 = d5, t8 = u5, b8 = X5;
function a9(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 t9(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);
}
/*!
* This file contains all constants used in the codex package.
*
* Exported constants should be marked with `@public` comments in this file, AND explicitly
* exported in lib.ts.
*
* IMPORTANT NOTE: All constants should be added to the Types and Constants page on the Codex docs
* site. Refer to `packages/codex-docs/docs/components/types-and-constants.md`.
*/
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 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 && t9(props.icon, overriddenLang.value),
["cdx-icon--".concat(props.size)]: true
}));
const resolvedIcon = computed(
() => {
var _a, _b;
return a9(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 _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
},
/**
* 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
}));
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: _4
}
},
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$2 = {
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$2, [
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
/* HOISTED */
)),
_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 */
)) : createCommentVNod