@limetech/lime-elements 38.28.0 → 38.28.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1 +1 @@
1
- {"file":"limel-list-item.entry.js","mappings":";;;;;;AAsCO,MAAM,mBAAmB,GAE5B,CAAC,KAAK;EACN,QACI,WACI,KAAK,EAAE;MACH,eAAe,EAAE,IAAI;MACrB,cAAc,EAAE,IAAI;MACpB,OAAO,EAAE,KAAK,CAAC,OAAO;MACtB,QAAQ,EAAE,KAAK,CAAC,QAAQ;KAC3B;IAED,aACI,IAAI,EAAC,OAAO,EACZ,EAAE,EAAE,KAAK,CAAC,EAAE,EACZ,OAAO,EAAE,KAAK,CAAC,OAAO,EACtB,QAAQ,EAAE,KAAK,CAAC,QAAQ,EACxB,QAAQ,EAAE,KAAK,CAAC,QAAQ,GAC1B;IACF,WAAK,KAAK,EAAC,KAAK,GAAG;IACnB,aAAO,KAAK,EAAC,qBAAqB,EAAC,OAAO,EAAE,KAAK,CAAC,EAAE,IAC/C,KAAK,CAAC,KAAK,CACR,CACN,EACR;AACN,CAAC;;AC/DD,MAAM,WAAW,GAAG,y1QAAy1Q;;MC2Dh2Q,iBAAiB;EA+G1B;;;IA+CQ,gBAAW,GAAG;MAClB,QACI,YAAM,KAAK,EAAC,OAAO,EAAC,EAAE,EAAE,IAAI,CAAC,OAAO,IAC/B,IAAI,CAAC,IAAI,CACP,EACT;KACL,CAAC;IAEM,sBAAiB,GAAG;MACxB,IAAI,CAAC,IAAI,CAAC,aAAa,EAAE;QACrB,OAAO;OACV;MAED,QACI,YAAM,KAAK,EAAC,aAAa,EAAC,EAAE,EAAE,IAAI,CAAC,aAAa,IAC3C,IAAI,CAAC,aAAa,CAChB,EACT;KACL,CAAC;IAEM,eAAU,GAAG;MACjB,MAAM,QAAQ,GAAG,WAAW,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;MACxC,IAAI,CAAC,QAAQ,EAAE;QACX,OAAO;OACV;MAED,IAAI,SAA6B,CAAC;MAClC,IAAI,mBAAuC,CAAC;MAC5C,IAAI,KAAyB,CAAC;MAE9B,IAAI,OAAO,IAAI,CAAC,IAAI,KAAK,QAAQ,EAAE;QAC/B,SAAS,GAAG,IAAI,CAAC,IAAI,CAAC,KAAK,CAAC;QAC5B,mBAAmB,GAAG,IAAI,CAAC,IAAI,CAAC,eAAe,CAAC;QAChD,KAAK,GAAG,IAAI,CAAC,IAAI,CAAC,KAAK,CAAC;OAC3B;MAED,MAAM,SAAS,GAAG;QACd,YAAY,EAAE,KAAK;QACnB,aAAa,EAAE,KAAK,GAAG,IAAI,GAAG,MAAM;QACpC,IAAI,EAAE,QAAQ;QACd,KAAK,EAAE;UACH,KAAK,EAAE,SAAS;UAChB,kBAAkB,EAAE,mBAAmB;SAC1C;QACD,KAAK,EAAE,IAAI,CAAC,SAAS;QACrB,IAAI,EAAE,IAAI,CAAC,QAAQ;OACtB,CAAC;MAEF,OAAO,kCAAgB,SAAS,EAAI,CAAC;KACxC,CAAC;IAEM,2BAAsB,GAAG;MAC7B,MAAM,OAAO,GAAG,IAAI,CAAC,gBAAgB,CAAC;MACtC,IAAI,EAAC,OAAO,aAAP,OAAO,uBAAP,OAAO,CAAE,IAAI,CAAA,EAAE;QAChB,OAAO;OACV;MAED,MAAM,gBAAgB,GAAQ,OAAO,CAAC,IAAI,CAAC;MAC3C,MAAM,KAAK,GAAG,OAAO,CAAC,KAAK,IAAI,EAAE,CAAC;MAElC,OAAO,EAAC,gBAAgB,oBAAK,KAAK,EAAI,CAAC;KAC1C,CAAC;IAEM,gBAAW,GAAG;MAClB,IAAI,CAAC,IAAI,CAAC,KAAK,EAAE;QACb,OAAO;OACV;MAED,OAAO,WAAK,GAAG,EAAE,IAAI,CAAC,KAAK,CAAC,GAAG,EAAE,GAAG,EAAE,IAAI,CAAC,KAAK,CAAC,GAAG,EAAE,OAAO,EAAC,MAAM,GAAG,CAAC;KAC3E,CAAC;IAEM,qBAAgB,GAAG,CAAC,OAAwC;MAChE,IAAI,CAAC,OAAO,IAAI,OAAO,CAAC,MAAM,KAAK,CAAC,EAAE;QAClC,OAAO;OACV;MAED,MAAM,aAAa,GAAG,IAAI,CAAC,gBAAgB,CAAC,OAAO,CAAC,CAAC;MACrD,QACI,kBACI,KAAK,EAAC,gCAAgC,EACtC,KAAK,EAAE,aAAa,EACpB,aAAa,EAAC,YAAY,IAE1B,yBACI,KAAK,EAAC,qBAAqB,EAC3B,IAAI,EAAC,SAAS,EACd,IAAI,EAAC,QAAQ,EACb,KAAK,EAAE,IAAI,CAAC,eAAe,EAAE,GAC/B,CACO,EACf;KACL,CAAC;IAmBM,sBAAiB,GAAG;MACxB,IAAI,IAAI,CAAC,IAAI,KAAK,OAAO,EAAE;QACvB,OAAO;OACV;MAED,QACI,EAAC,mBAAmB,IAChB,EAAE,EAAE,SAAS,IAAI,CAAC,OAAO,EAAE,EAC3B,OAAO,EAAE,IAAI,CAAC,QAAQ,EACtB,QAAQ,EAAE,IAAI,CAAC,QAAQ,GACzB,EACJ;KACL,CAAC;IAEM,mBAAc,GAAG;MACrB,IAAI,IAAI,CAAC,IAAI,KAAK,UAAU,EAAE;QAC1B,OAAO;OACV;MAED,QACI,EAAC,gBAAgB,IACb,EAAE,EAAE,YAAY,IAAI,CAAC,OAAO,EAAE,EAC9B,OAAO,EAAE,IAAI,CAAC,QAAQ,EACtB,QAAQ,EAAE,IAAI,CAAC,QAAQ,GACzB,EACJ;KACL,CAAC;IAEM,YAAO,GAAG,CAAC,KAAiB;MAChC,IAAI,IAAI,CAAC,QAAQ,EAAE;;QAEf,OAAO;OACV;MAED,MAAM,MAAM,GAAG,KAAK,CAAC,MAA4B,CAAC;MAClD,MAAM,qBAAqB,GAAG,CAAC,EAAC,MAAM,aAAN,MAAM,uBAAN,MAAM,CAAE,OAAO,CAAC,sBAAsB,CAAC,CAAA,CAAC;MACxE,MAAM,gBAAgB,GAAG,CAAC,EAAC,MAAM,aAAN,MAAM,uBAAN,MAAM,CAAE,OAAO,CAAC,kBAAkB,CAAC,CAAA,CAAC;MAC/D,MAAM,YAAY,GAAG,CAAC,EAAC,MAAM,aAAN,MAAM,uBAAN,MAAM,CAAE,OAAO,CAAC,YAAY,CAAC,CAAA,CAAC;MACrD,IAAI,qBAAqB,IAAI,gBAAgB,IAAI,YAAY,EAAE;QAC3D,OAAO;OACV;MAED,IAAI,IAAI,CAAC,gBAAgB,EAAE,EAAE;QACzB,IAAI,CAAC,iBAAiB,EAAE,CAAC;OAC5B;;KAEJ,CAAC;IAEM,cAAS,GAAG,CAAC,KAAoB;MACrC,IAAI,IAAI,CAAC,QAAQ,EAAE;QACf,OAAO;OACV;;;;MAKD,MAAM,UAAU,GAAG,IAAI,CAAC,IAAI,CAAC,UAAU,CAAC;MACxC,MAAM,aAAa,GAAG,UAAU;UACzB,UAAU,CAAC,aAAoC;UAChD,IAAI,CAAC;MACX,IAAI,aAAa,IAAI,aAAa,KAAK,IAAI,CAAC,IAAI,EAAE;QAC9C,OAAO;OACV;MAED,MAAM,OAAO,GAAG,KAAK,CAAC,GAAG,KAAK,OAAO,CAAC;MACtC,MAAM,OAAO,GACT,KAAK,CAAC,GAAG,KAAK,GAAG;QACjB,KAAK,CAAC,GAAG,KAAK,OAAO;QACrB,KAAK,CAAC,GAAG,KAAK,UAAU;QACxB,KAAK,CAAC,IAAI,KAAK,OAAO,CAAC;MAE3B,IAAI,CAAC,OAAO,IAAI,CAAC,OAAO,EAAE;QACtB,OAAO;OACV;;MAGD,IAAI,KAAK,CAAC,MAAM,EAAE;;QAEd,IAAI,OAAO,EAAE;UACT,KAAK,CAAC,cAAc,EAAE,CAAC;SAC1B;QACD,OAAO;OACV;;MAGD,IAAI,OAAO,EAAE;QACT,KAAK,CAAC,cAAc,EAAE,CAAC;OAC1B;MAED,IAAI,IAAI,CAAC,gBAAgB,EAAE,EAAE;QACzB,IAAI,CAAC,iBAAiB,EAAE,CAAC;QACzB,OAAO;OACV;;MAGD,IAAI,OAAO,IAAI,OAAO,EAAE;QACpB,IAAI,CAAC,IAAI,CAAC,KAAK,EAAE,CAAC;OACrB;KACJ,CAAC;IA8BM,sBAAiB,GAAG;MACxB,MAAM,WAAW,GAAG,CAAC,IAAI,CAAC,QAAQ,CAAC;MAEnC,MAAM,IAAI,GAAa;QACnB,IAAI,EAAE,IAAI,CAAC,IAAI;QACf,aAAa,EAAE,IAAI,CAAC,aAAa;QACjC,QAAQ,EAAE,IAAI,CAAC,QAAQ;QACvB,IAAI,EAAE,IAAI,CAAC,IAAI;QACf,QAAQ,EAAE,WAAW;QACrB,KAAK,EAAE,IAAI,CAAC,KAAK;QACjB,OAAO,EAAE,IAAI,CAAC,OAAO;QACrB,gBAAgB,EAAE,IAAI,CAAC,gBAAgB;QACvC,KAAK,EAAE,IAAI,CAAC,KAAK;OACpB,CAAC;MAEF,IAAI,CAAC,QAAQ,CAAC,IAAI,CAAC;QACf,QAAQ,EAAE,WAAW;QACrB,IAAI,EAAE,IAAI;OACb,CAAC,CAAC;KACN,CAAC;IAEM,oBAAe,GAAG;MACtB,OAAO,SAAS,CAAC,GAAG,CAAC,0BAA0B,EAAE,IAAI,CAAC,QAAQ,CAAC,CAAC;KACnE,CAAC;oBA7Z2B,IAAI;;;;oBAwBf,KAAK;;oBAYK,OAAO;qBAMhB,KAAK;oBAMN,KAAK;;;;gBA8BnB,UAAU;IA4BV,IAAI,CAAC,OAAO,GAAG,kBAAkB,EAAE,CAAC;IACpC,IAAI,CAAC,aAAa,GAAG,kBAAkB,EAAE,CAAC;GAC7C;EAEM,MAAM;;IACT,MAAM,SAAS,GAAQ;MACnB,iBAAiB,EAAE,IAAI,CAAC,OAAO;MAC/B,kBAAkB,EAAE,IAAI,CAAC,aAAa;UAChC,IAAI,CAAC,aAAa;UAClB,SAAS;MACf,eAAe,EAAE,IAAI,CAAC,QAAQ,GAAG,MAAM,GAAG,OAAO;KACpD,CAAC;;IAGF,IAAI,IAAI,CAAC,IAAI,KAAK,OAAO,IAAI,IAAI,CAAC,IAAI,KAAK,UAAU,EAAE;MACnD,SAAS,CAAC,cAAc,CAAC,GAAG,IAAI,CAAC,QAAQ,GAAG,MAAM,GAAG,OAAO,CAAC;KAChE;SAAM,IAAI,IAAI,CAAC,IAAI,KAAK,QAAQ,IAAI,IAAI,CAAC,IAAI,KAAK,UAAU,EAAE;;;MAG3D,SAAS,CAAC,eAAe,CAAC,GAAG,IAAI,CAAC,QAAQ,GAAG,MAAM,GAAG,OAAO,CAAC;KACjE;IAED,QACI,EAAC,IAAI,kBACD,IAAI,EAAE,IAAI,CAAC,WAAW,EAAE,EACxB,KAAK,EAAE;QACH,uBAAuB,EAAE,CAAC,EAAC,MAAA,IAAI,CAAC,gBAAgB,0CAAE,IAAI,CAAA;OACzD,IACG,SAAS,IACb,OAAO,EAAE,IAAI,CAAC,OAAO,EACrB,SAAS,EAAE,IAAI,CAAC,SAAS,KAExB,IAAI,CAAC,iBAAiB,EAAE,EACxB,IAAI,CAAC,cAAc,EAAE,EACrB,IAAI,CAAC,UAAU,EAAE,EACjB,IAAI,CAAC,WAAW,EAAE,EAClB,IAAI,CAAC,sBAAsB,EAAE,EAC9B,WAAK,KAAK,EAAC,MAAM,IACZ,IAAI,CAAC,WAAW,EAAE,EAClB,IAAI,CAAC,iBAAiB,EAAE,CACvB,EACL,IAAI,CAAC,gBAAgB,CAAC,IAAI,CAAC,OAAO,CAAC,CACjC,EACT;GACL;;;;;;;;EAsGO,gBAAgB,CACpB,OAAwC;IAExC,IAAI,IAAI,CAAC,eAAe,KAAK,OAAO,EAAE;MAClC,OAAO,IAAI,CAAC,eAAe,CAAC;KAC/B;IACD,IAAI,CAAC,eAAe,GAAG,OAAO,CAAC;IAC/B,OAAO,OAAO,CAAC;GAClB;EAsGO,gBAAgB;IACpB,QACI,IAAI,CAAC,IAAI,KAAK,QAAQ;MACtB,IAAI,CAAC,IAAI,KAAK,OAAO;MACrB,IAAI,CAAC,IAAI,KAAK,UAAU,EAC1B;GACL;EAEO,WAAW;IACf,QAAQ,IAAI,CAAC,IAAI;MACb,KAAK,QAAQ,EAAE;QACX,OAAO,QAAQ,CAAC;OACnB;MACD,KAAK,OAAO,EAAE;QACV,OAAO,OAAO,CAAC;OAClB;MACD,KAAK,UAAU,EAAE;QACb,OAAO,UAAU,CAAC;OACrB;MACD,KAAK,UAAU,EAAE;QACb,OAAO,UAAU,CAAC;OACrB;MACD,SAAS;QACL,OAAO,UAAU,CAAC;OACrB;KACJ;GACJ;;;;;;;","names":[],"sources":["./src/components/radio-button-group/radio-button.template.tsx","./src/components/list-item/list-item.scss?tag=limel-list-item","./src/components/list-item/list-item.tsx"],"sourcesContent":["import { FunctionalComponent, h } from '@stencil/core';\n\n/**\n * Radio Button Template\n *\n * This is a low-level template component that renders individual radio button elements\n * using Material Design Components (MDC) styling and structure. It's used internally\n * by the list component to render radio buttons when `type=\"radio\"` is specified.\n *\n * ## Usage in the Library\n *\n * This template is primarily used by:\n * - `limel-list` component when `type=\"radio\"`\n * - `limel-radio-button-group` component (which wraps `limel-list`)\n *\n * ## Why This Exists\n *\n * While we have `limel-radio-button-group` for most use cases, this template provides\n * the actual radio button HTML structure with proper MDC classes and accessibility\n * attributes. It ensures consistent styling and behavior across all radio button\n * implementations in the library.\n *\n * ## Design Philosophy\n *\n * This follows the principle that individual radio buttons should not be standalone\n * components, as a single radio button is never useful in a UI. Instead, this template\n * is used to build groups of radio buttons through higher-level components.\n *\n * @internal\n */\ninterface RadioButtonTemplateProps {\n disabled?: boolean;\n id: string;\n checked?: boolean;\n onChange?: (event: Event) => void;\n label?: string;\n}\n\nexport const RadioButtonTemplate: FunctionalComponent<\n RadioButtonTemplateProps\n> = (props) => {\n return (\n <div\n class={{\n 'boolean-input': true,\n 'radio-button': true,\n checked: props.checked,\n disabled: props.disabled,\n }}\n >\n <input\n type=\"radio\"\n id={props.id}\n checked={props.checked}\n disabled={props.disabled}\n onChange={props.onChange}\n />\n <div class=\"box\" />\n <label class=\"boolean-input-label\" htmlFor={props.id}>\n {props.label}\n </label>\n </div>\n );\n};\n","/**\n * @prop --notification-badge-text-color: (Publicly documented in `limel-menu` too) Defines the text color of notification badges. Defaults to `--color-white`.\n * @prop --notification-badge-background-color: (Publicly documented in `limel-menu` too) Defines the background color of notification badges. Defaults to `--color-red-default`.\n * @prop --limel-list-item-menu-order: Defines the order of the menu, within the list item's flexbox. Defaults to `3`.\n */\n\n@use '../../style/mixins';\n@forward '../checkbox/checkbox.scss';\n@forward '../radio-button-group/radio-button.scss';\n\n*,\n*:before,\n*:after {\n box-sizing: border-box;\n}\n\nlimel-list-item {\n min-height: 2.5rem;\n @include mixins.visualize-keyboard-focus();\n\n transition: background-color 0.6s ease;\n position: relative;\n isolation: isolate;\n\n display: flex;\n align-items: center;\n gap: 0.5rem;\n\n padding: 0 1rem;\n background-color: rgb(var(--contrast-100));\n\n &:hover {\n z-index: 1;\n transition: background-color 0.2s ease;\n border-radius: 0.5rem;\n }\n\n &:focus,\n &:focus-visible,\n &:active {\n z-index: 1;\n border-radius: 0.5rem;\n }\n\n &:first-of-type {\n border-top-left-radius: 0.5rem;\n border-top-right-radius: 0.5rem;\n }\n\n &:last-of-type {\n border-bottom-left-radius: 0.5rem;\n border-bottom-right-radius: 0.5rem;\n }\n\n &:not([disabled]):not([disabled='true']) {\n cursor: pointer;\n }\n\n &[disabled]:not([disabled='false']) {\n cursor: not-allowed;\n }\n}\n\nlimel-list-item[disabled]:not([disabled='false']) {\n cursor: not-allowed;\n\n .text,\n limel-icon,\n img,\n .boolean-input {\n opacity: 0.4;\n }\n}\n\nlimel-list-item:not([disabled]):not([disabled='true']):hover,\nlimel-list-item:not([disabled]):not([disabled='true']):focus-visible {\n background-color: rgb(var(--contrast-400));\n}\n\nlimel-list-item[type='option'] {\n &:before {\n transition: background-color 0.6s ease;\n content: '';\n position: absolute;\n inset: 0;\n\n opacity: 0.2;\n border-radius: 0.5rem;\n }\n\n &[selected]:not([selected='false']) {\n &:before {\n transition: background-color 0.2s ease;\n background-color: var(--limel-theme-primary-color);\n }\n }\n}\n\nlimel-list-item {\n .text {\n flex-grow: 1;\n min-width: 0;\n\n display: flex;\n flex-direction: column;\n\n padding: 0.5rem 0;\n\n color: var(--limel-theme-text-primary-on-background-color);\n }\n\n .label {\n @include mixins.truncate-text();\n\n font-size: var(--limel-theme-default-font-size);\n line-height: 1rem;\n }\n\n .description {\n @include mixins.truncate-text-on-line(var(--maxLinesSecondaryText));\n line-height: 1rem;\n font-size: var(--limel-theme-default-small-font-size);\n opacity: 0.6;\n }\n\n limel-icon {\n color: var(--limel-theme-text-secondary-on-background-color);\n flex-shrink: 0;\n margin-left: -0.5rem;\n\n &:has(+ img) {\n margin-left: 0;\n position: absolute;\n top: 0.125rem;\n left: 0.125rem;\n padding: 0.1875rem;\n width: 1.25rem;\n background-color: rgb(var(--contrast-200), 0.8);\n }\n }\n\n img {\n flex-shrink: 0;\n object-fit: cover;\n border-radius: 50%;\n width: 2rem;\n height: 2rem;\n box-shadow: 0 0 0 1px rgb(var(--contrast-800), 0.5);\n }\n\n limel-menu {\n margin-right: -0.5rem;\n // Sometimes, `primaryComponent`s in list items need to get\n // `order: 2;` to be placed after the text. But since the default `order`\n // of all lit item children is `0`, we need to push the menu to the far right\n // by giving it a bigger order number. Also, by making this into a variable\n // we can handle other edge-cases in consuming components.\n order: var(--limel-list-item-menu-order, 3);\n }\n}\n\nlimel-list-item {\n &[role='menuitem'] & {\n .label {\n font-size: var(--limel-theme-default-small-font-size);\n }\n }\n}\n\n// ====================\n// Checkbox and radios\n.boolean-input {\n width: var(--limel-boolean-input-box-size);\n margin-left: -0.25rem;\n &.checkbox {\n margin-right: 0.25rem;\n }\n\n limel-list-item:has(limel-icon) &,\n limel-list-item:has(img) & {\n margin-right: -0.25rem;\n margin-left: 0;\n order: 2;\n }\n}\n\n.boolean-input-label {\n @include mixins.truncate-text();\n opacity: 0;\n width: var(--limel-boolean-input-box-size);\n}\n// ====================\n","import {\n Component,\n Host,\n Prop,\n h,\n Event,\n EventEmitter,\n Element,\n} from '@stencil/core';\nimport { getIconName } from '../icon/get-icon-props';\nimport type { IconSize } from '../icon/icon.types';\nimport { createRandomString } from '../../util/random-string';\nimport { ListItem } from './list-item.types';\nimport { MenuItem } from '../menu/menu.types';\nimport { ListSeparator } from '../../global/shared-types/separator.types';\nimport { CheckboxTemplate } from '../checkbox/checkbox.template';\nimport { RadioButtonTemplate } from '../radio-button-group/radio-button.template';\nimport translate from '../../global/translations';\nimport { Languages } from '../date-picker/date.types';\n\n/**\n * This components displays the list item.\n * This centralizes styles and functionality, and helps reduce redundant code\n * in consumer components such as `limel-list` and `limel-menu-list`.\n *\n * :::note\n * The component has `shadow: false`. There are a few reasons for it:\n * 1. This is to improve performance, and ensure that its internal elements are\n * considered as internal parts of the consumer's DOM.\n * 2. The consumer does not need to implement the interactive styles\n * (such as `visualize-keyboard-focus` mixin) on their own. Since there is no\n * shadow DOM, our mixins can be applied directly to the `limel-list-item` elements,\n * within the component's own styles.\n * 3. Most importantly, the MDCList checks the light DOM of each list item\n * to find native inputs to decide the list mode (checkbox/radio).\n * With `shadow: true`, those inputs would be hidden inside the `limel-list-items`’s\n * shadow DOM, so MDC wouldn’t detect them and therefore throw errors, when given\n * an array index (for the items).\n * With `shadow: false`, the native `<input type=\"checkbox/radio\">` from this template\n * would be visible to MDC.\n * :::\n * @exampleComponent limel-example-list-item-basic\n * @exampleComponent limel-example-list-item-icon\n * @exampleComponent limel-example-list-item-icon-size\n * @exampleComponent limel-example-list-item-pictures\n * @exampleComponent limel-example-list-item-multiple-lines\n * @exampleComponent limel-example-list-item-interactive\n * @exampleComponent limel-example-list-item-radio\n * @exampleComponent limel-example-list-item-checkbox\n * @exampleComponent limel-example-list-item-actions\n * @exampleComponent limel-example-list-item-primary-component\n * @exampleComponent limel-example-list-item-command-text\n * @private\n */\n@Component({\n tag: 'limel-list-item',\n shadow: false,\n styleUrl: 'list-item.scss',\n})\nexport class ListItemComponent implements ListItem {\n /**\n * Defines the language for translations.\n * Will translate the translatable strings on the components.\n */\n @Prop({ reflect: true })\n public language: Languages = 'en';\n\n /**\n * {@inheritdoc ListItem.value}\n */\n @Prop()\n public value?: any;\n\n /**\n * {@inheritdoc ListItem.text}\n */\n @Prop({ reflect: true })\n public text: string;\n\n /**\n * {@inheritdoc ListItem.secondaryText}\n */\n @Prop({ reflect: true })\n public secondaryText?: string;\n\n /**\n * {@inheritdoc ListItem.disabled}\n */\n @Prop({ reflect: true })\n public disabled = false;\n\n /**\n * {@inheritdoc ListItem.icon}\n */\n @Prop()\n public icon?: string | ListItem['icon'];\n\n /**\n * Size of the icon displayed for this item.\n */\n @Prop({ reflect: true })\n public iconSize: IconSize = 'small';\n\n /**\n * Set to `true` if the list should display larger icons with a background\n */\n @Prop({ reflect: true })\n public badgeIcon = false;\n\n /**\n * {@inheritdoc ListItem.selected}\n */\n @Prop({ reflect: true })\n public selected = false;\n\n /**\n * {@inheritdoc ListItem.selected}\n */\n @Prop()\n public actions?: ListItem['actions'];\n\n /**\n * {@inheritdoc ListItem.selected}\n */\n @Prop()\n public primaryComponent?: ListItem['primaryComponent'];\n\n /**\n * {@inheritdoc ListItem.image}\n */\n @Prop()\n public image?: ListItem['image'];\n\n /**\n * The semantic role of the list item. This affects the ARIA role\n * and the interaction behavior.\n *\n * - 'option' → selectable via click/Enter/Space, aria-selected\n * - 'radio'/'checkbox' → selectable, aria-checked\n * - 'menuitem'/'listitem' → activation only, no selection toggle\n */\n @Prop({ reflect: true })\n public type: 'listitem' | 'menuitem' | 'option' | 'radio' | 'checkbox' =\n 'listitem';\n\n /**\n * Emitted when the list item toggles selection (only for selectable types and not disabled).\n */\n @Event()\n public interact: EventEmitter<{\n selected: boolean;\n item: ListItem;\n }>;\n\n @Element()\n private host: HTMLLimelListItemElement;\n\n /**\n * Used to describe the list item for assistive technology.\n */\n private readonly descriptionId: string;\n\n /**\n * Used to label the list item for assistive technology.\n */\n private readonly labelId: string;\n\n // Memoized reference for the action items to avoid unnecessary updates\n private memoizedActions?: Array<MenuItem | ListSeparator>;\n\n constructor() {\n this.labelId = createRandomString();\n this.descriptionId = createRandomString();\n }\n\n public render() {\n const ariaProps: any = {\n 'aria-labelledby': this.labelId,\n 'aria-describedby': this.secondaryText\n ? this.descriptionId\n : undefined,\n 'aria-disabled': this.disabled ? 'true' : 'false',\n };\n\n // ARIA state depending on `role`/`type`\n if (this.type === 'radio' || this.type === 'checkbox') {\n ariaProps['aria-checked'] = this.selected ? 'true' : 'false';\n } else if (this.type === 'option' || this.type === 'menuitem') {\n // aria-selected for `option` (spec);\n // also keep for `menuitem` for visual state consistency\n ariaProps['aria-selected'] = this.selected ? 'true' : 'false';\n }\n\n return (\n <Host\n role={this.getHostRole()}\n class={{\n 'has-primary-component': !!this.primaryComponent?.name,\n }}\n {...ariaProps}\n onClick={this.onClick}\n onKeyDown={this.onKeyDown}\n >\n {this.renderRadioButton()}\n {this.renderCheckbox()}\n {this.renderIcon()}\n {this.renderImage()}\n {this.renderPrimaryComponent()}\n <div class=\"text\">\n {this.renderLabel()}\n {this.renderDescription()}\n </div>\n {this.renderActionMenu(this.actions)}\n </Host>\n );\n }\n\n private renderLabel = () => {\n return (\n <span class=\"label\" id={this.labelId}>\n {this.text}\n </span>\n );\n };\n\n private renderDescription = () => {\n if (!this.secondaryText) {\n return;\n }\n\n return (\n <span class=\"description\" id={this.descriptionId}>\n {this.secondaryText}\n </span>\n );\n };\n\n private renderIcon = () => {\n const iconName = getIconName(this.icon);\n if (!iconName) {\n return;\n }\n\n let iconColor: string | undefined;\n let iconBackgroundColor: string | undefined;\n let title: string | undefined;\n\n if (typeof this.icon === 'object') {\n iconColor = this.icon.color;\n iconBackgroundColor = this.icon.backgroundColor;\n title = this.icon.title;\n }\n\n const iconProps = {\n 'aria-label': title,\n 'aria-hidden': title ? null : 'true',\n name: iconName,\n style: {\n color: iconColor,\n 'background-color': iconBackgroundColor,\n },\n badge: this.badgeIcon,\n size: this.iconSize,\n };\n\n return <limel-icon {...iconProps} />;\n };\n\n private renderPrimaryComponent = () => {\n const primary = this.primaryComponent;\n if (!primary?.name) {\n return;\n }\n\n const PrimaryComponent: any = primary.name;\n const props = primary.props || {};\n\n return <PrimaryComponent {...props} />;\n };\n\n private renderImage = () => {\n if (!this.image) {\n return;\n }\n\n return <img src={this.image.src} alt={this.image.alt} loading=\"lazy\" />;\n };\n\n private renderActionMenu = (actions: Array<MenuItem | ListSeparator>) => {\n if (!actions || actions.length === 0) {\n return;\n }\n\n const stableActions = this.getStableActions(actions);\n return (\n <limel-menu\n class=\"mdc-deprecated-list-item__meta\"\n items={stableActions}\n openDirection=\"left-start\"\n >\n <limel-icon-button\n class=\"action-menu-trigger\"\n slot=\"trigger\"\n icon=\"menu_2\"\n label={this.actionMenuLabel()}\n />\n </limel-menu>\n );\n };\n\n /**\n * Returns a stable reference for the provided actions array to avoid\n * unnecessary re-renders of the action menu when the reference is unchanged.\n *\n * @param actions The actions (and separators) to display in the menu\n * @returns The same array instance that was previously seen, if unchanged\n */\n private getStableActions(\n actions: Array<MenuItem | ListSeparator>\n ): Array<MenuItem | ListSeparator> {\n if (this.memoizedActions === actions) {\n return this.memoizedActions;\n }\n this.memoizedActions = actions;\n return actions;\n }\n\n private renderRadioButton = () => {\n if (this.type !== 'radio') {\n return;\n }\n\n return (\n <RadioButtonTemplate\n id={`radio_${this.labelId}`}\n checked={this.selected}\n disabled={this.disabled}\n />\n );\n };\n\n private renderCheckbox = () => {\n if (this.type !== 'checkbox') {\n return;\n }\n\n return (\n <CheckboxTemplate\n id={`checkbox_${this.labelId}`}\n checked={this.selected}\n disabled={this.disabled}\n />\n );\n };\n\n private onClick = (event: MouseEvent) => {\n if (this.disabled) {\n // Ignore toggling, but don't block embedded controls\n return;\n }\n\n const target = event.target as HTMLElement | null;\n const cameFromActionTrigger = !!target?.closest('.action-menu-trigger');\n const cameFromNoToggle = !!target?.closest('[data-no-toggle]');\n const cameFromMenu = !!target?.closest('limel-menu');\n if (cameFromActionTrigger || cameFromNoToggle || cameFromMenu) {\n return;\n }\n\n if (this.isSelectableType()) {\n this.handleInteraction();\n }\n // For non-selectable types (menuitem/listitem), allow native click to bubble\n };\n\n private onKeyDown = (event: KeyboardEvent) => {\n if (this.disabled) {\n return;\n }\n\n // Only handle keyboard when the host itself has focus.\n // This avoids toggling when Space/Enter is pressed on inner controls\n // like the action menu trigger or any primary component.\n const shadowRoot = this.host.shadowRoot;\n const activeElement = shadowRoot\n ? (shadowRoot.activeElement as HTMLElement | null)\n : null;\n if (activeElement && activeElement !== this.host) {\n return;\n }\n\n const isEnter = event.key === 'Enter';\n const isSpace =\n event.key === ' ' ||\n event.key === 'Space' ||\n event.key === 'Spacebar' ||\n event.code === 'Space';\n\n if (!isEnter && !isSpace) {\n return;\n }\n\n // Avoid re-triggering while key is held down and auto-repeats\n if (event.repeat) {\n // Also prevent default scroll on Space when repeating\n if (isSpace) {\n event.preventDefault();\n }\n return;\n }\n\n // Prevent page scroll and default button behavior on Space\n if (isSpace) {\n event.preventDefault();\n }\n\n if (this.isSelectableType()) {\n this.handleInteraction();\n return;\n }\n\n // For non-selectable items, treat Enter and Space as activation (simulate click)\n if (isEnter || isSpace) {\n this.host.click();\n }\n };\n\n private isSelectableType(): boolean {\n return (\n this.type === 'option' ||\n this.type === 'radio' ||\n this.type === 'checkbox'\n );\n }\n\n private getHostRole(): string {\n switch (this.type) {\n case 'option': {\n return 'option';\n }\n case 'radio': {\n return 'radio';\n }\n case 'checkbox': {\n return 'checkbox';\n }\n case 'menuitem': {\n return 'menuitem';\n }\n default: {\n return 'listitem';\n }\n }\n }\n\n private handleInteraction = () => {\n const newSelected = !this.selected;\n\n const item: ListItem = {\n text: this.text,\n secondaryText: this.secondaryText,\n disabled: this.disabled,\n icon: this.icon,\n selected: newSelected,\n value: this.value,\n actions: this.actions,\n primaryComponent: this.primaryComponent,\n image: this.image,\n };\n\n this.interact.emit({\n selected: newSelected,\n item: item,\n });\n };\n\n private actionMenuLabel = (): string => {\n return translate.get('file-viewer.more-actions', this.language);\n };\n}\n"],"version":3}
1
+ {"file":"limel-list-item.entry.js","mappings":";;;;;;AAsCO,MAAM,mBAAmB,GAE5B,CAAC,KAAK;EACN,QACI,WACI,KAAK,EAAE;MACH,eAAe,EAAE,IAAI;MACrB,cAAc,EAAE,IAAI;MACpB,OAAO,EAAE,KAAK,CAAC,OAAO;MACtB,QAAQ,EAAE,KAAK,CAAC,QAAQ;KAC3B;IAED,aACI,IAAI,EAAC,OAAO,EACZ,EAAE,EAAE,KAAK,CAAC,EAAE,EACZ,OAAO,EAAE,KAAK,CAAC,OAAO,EACtB,QAAQ,EAAE,KAAK,CAAC,QAAQ,EACxB,QAAQ,EAAE,KAAK,CAAC,QAAQ,GAC1B;IACF,WAAK,KAAK,EAAC,KAAK,GAAG;IACnB,aAAO,KAAK,EAAC,qBAAqB,EAAC,OAAO,EAAE,KAAK,CAAC,EAAE,IAC/C,KAAK,CAAC,KAAK,CACR,CACN,EACR;AACN,CAAC;;AC/DD,MAAM,WAAW,GAAG,y1QAAy1Q;;MCmDh2Q,iBAAiB;EAmG1B;;IA6CQ,gBAAW,GAAG;MAClB,QACI,YAAM,KAAK,EAAC,OAAO,EAAC,EAAE,EAAE,IAAI,CAAC,OAAO,IAC/B,IAAI,CAAC,IAAI,CACP,EACT;KACL,CAAC;IAEM,sBAAiB,GAAG;MACxB,IAAI,CAAC,IAAI,CAAC,aAAa,EAAE;QACrB,OAAO;OACV;MAED,QACI,YAAM,KAAK,EAAC,aAAa,EAAC,EAAE,EAAE,IAAI,CAAC,aAAa,IAC3C,IAAI,CAAC,aAAa,CAChB,EACT;KACL,CAAC;IAEM,eAAU,GAAG;MACjB,MAAM,QAAQ,GAAG,WAAW,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;MACxC,IAAI,CAAC,QAAQ,EAAE;QACX,OAAO;OACV;MAED,IAAI,SAA6B,CAAC;MAClC,IAAI,mBAAuC,CAAC;MAC5C,IAAI,KAAyB,CAAC;MAE9B,IAAI,OAAO,IAAI,CAAC,IAAI,KAAK,QAAQ,EAAE;QAC/B,SAAS,GAAG,IAAI,CAAC,IAAI,CAAC,KAAK,CAAC;QAC5B,mBAAmB,GAAG,IAAI,CAAC,IAAI,CAAC,eAAe,CAAC;QAChD,KAAK,GAAG,IAAI,CAAC,IAAI,CAAC,KAAK,CAAC;OAC3B;MAED,MAAM,SAAS,GAAG;QACd,YAAY,EAAE,KAAK;QACnB,aAAa,EAAE,KAAK,GAAG,IAAI,GAAG,MAAM;QACpC,IAAI,EAAE,QAAQ;QACd,KAAK,EAAE;UACH,KAAK,EAAE,SAAS;UAChB,kBAAkB,EAAE,mBAAmB;SAC1C;QACD,KAAK,EAAE,IAAI,CAAC,SAAS;QACrB,IAAI,EAAE,IAAI,CAAC,QAAQ;OACtB,CAAC;MAEF,OAAO,kCAAgB,SAAS,EAAI,CAAC;KACxC,CAAC;IAEM,2BAAsB,GAAG;MAC7B,MAAM,OAAO,GAAG,IAAI,CAAC,gBAAgB,CAAC;MACtC,IAAI,EAAC,OAAO,aAAP,OAAO,uBAAP,OAAO,CAAE,IAAI,CAAA,EAAE;QAChB,OAAO;OACV;MAED,MAAM,gBAAgB,GAAQ,OAAO,CAAC,IAAI,CAAC;MAC3C,MAAM,KAAK,GAAG,OAAO,CAAC,KAAK,IAAI,EAAE,CAAC;MAElC,OAAO,EAAC,gBAAgB,oBAAK,KAAK,EAAI,CAAC;KAC1C,CAAC;IAEM,gBAAW,GAAG;MAClB,IAAI,CAAC,IAAI,CAAC,KAAK,EAAE;QACb,OAAO;OACV;MAED,OAAO,WAAK,GAAG,EAAE,IAAI,CAAC,KAAK,CAAC,GAAG,EAAE,GAAG,EAAE,IAAI,CAAC,KAAK,CAAC,GAAG,EAAE,OAAO,EAAC,MAAM,GAAG,CAAC;KAC3E,CAAC;IAEM,qBAAgB,GAAG,CAAC,OAAwC;MAChE,IAAI,CAAC,OAAO,IAAI,OAAO,CAAC,MAAM,KAAK,CAAC,EAAE;QAClC,OAAO;OACV;MAED,MAAM,aAAa,GAAG,IAAI,CAAC,gBAAgB,CAAC,OAAO,CAAC,CAAC;MACrD,QACI,kBACI,KAAK,EAAC,gCAAgC,EACtC,KAAK,EAAE,aAAa,EACpB,aAAa,EAAC,YAAY,IAE1B,yBACI,KAAK,EAAC,qBAAqB,EAC3B,IAAI,EAAC,SAAS,EACd,IAAI,EAAC,QAAQ,EACb,KAAK,EAAE,IAAI,CAAC,eAAe,EAAE,GAC/B,CACO,EACf;KACL,CAAC;IAmBM,sBAAiB,GAAG;MACxB,IAAI,IAAI,CAAC,IAAI,KAAK,OAAO,EAAE;QACvB,OAAO;OACV;MAED,QACI,EAAC,mBAAmB,IAChB,EAAE,EAAE,SAAS,IAAI,CAAC,OAAO,EAAE,EAC3B,OAAO,EAAE,IAAI,CAAC,QAAQ,EACtB,QAAQ,EAAE,IAAI,CAAC,QAAQ,GACzB,EACJ;KACL,CAAC;IAEM,mBAAc,GAAG;MACrB,IAAI,IAAI,CAAC,IAAI,KAAK,UAAU,EAAE;QAC1B,OAAO;OACV;MAED,QACI,EAAC,gBAAgB,IACb,EAAE,EAAE,YAAY,IAAI,CAAC,OAAO,EAAE,EAC9B,OAAO,EAAE,IAAI,CAAC,QAAQ,EACtB,QAAQ,EAAE,IAAI,CAAC,QAAQ,GACzB,EACJ;KACL,CAAC;IAsBM,oBAAe,GAAG;MACtB,OAAO,SAAS,CAAC,GAAG,CAAC,0BAA0B,EAAE,IAAI,CAAC,QAAQ,CAAC,CAAC;KACnE,CAAC;oBA1S2B,IAAI;;;;oBAwBf,KAAK;;oBAYK,OAAO;qBAMhB,KAAK;oBAMN,KAAK;;;;gBA8BnB,UAAU;IAgBV,IAAI,CAAC,OAAO,GAAG,kBAAkB,EAAE,CAAC;IACpC,IAAI,CAAC,aAAa,GAAG,kBAAkB,EAAE,CAAC;GAC7C;EAEM,MAAM;;IACT,MAAM,SAAS,GAAQ;MACnB,iBAAiB,EAAE,IAAI,CAAC,OAAO;MAC/B,kBAAkB,EAAE,IAAI,CAAC,aAAa;UAChC,IAAI,CAAC,aAAa;UAClB,SAAS;MACf,eAAe,EAAE,IAAI,CAAC,QAAQ,GAAG,MAAM,GAAG,OAAO;KACpD,CAAC;;IAGF,IAAI,IAAI,CAAC,IAAI,KAAK,OAAO,IAAI,IAAI,CAAC,IAAI,KAAK,UAAU,EAAE;MACnD,SAAS,CAAC,cAAc,CAAC,GAAG,IAAI,CAAC,QAAQ,GAAG,MAAM,GAAG,OAAO,CAAC;KAChE;SAAM,IAAI,IAAI,CAAC,IAAI,KAAK,QAAQ,IAAI,IAAI,CAAC,IAAI,KAAK,UAAU,EAAE;;;MAG3D,SAAS,CAAC,eAAe,CAAC,GAAG,IAAI,CAAC,QAAQ,GAAG,MAAM,GAAG,OAAO,CAAC;KACjE;IAED,QACI,EAAC,IAAI,kBACD,IAAI,EAAE,IAAI,CAAC,WAAW,EAAE,EACxB,KAAK,EAAE;QACH,uBAAuB,EAAE,CAAC,EAAC,MAAA,IAAI,CAAC,gBAAgB,0CAAE,IAAI,CAAA;OACzD,IACG,SAAS,GAEZ,IAAI,CAAC,iBAAiB,EAAE,EACxB,IAAI,CAAC,cAAc,EAAE,EACrB,IAAI,CAAC,UAAU,EAAE,EACjB,IAAI,CAAC,WAAW,EAAE,EAClB,IAAI,CAAC,sBAAsB,EAAE,EAC9B,WAAK,KAAK,EAAC,MAAM,IACZ,IAAI,CAAC,WAAW,EAAE,EAClB,IAAI,CAAC,iBAAiB,EAAE,CACvB,EACL,IAAI,CAAC,gBAAgB,CAAC,IAAI,CAAC,OAAO,CAAC,CACjC,EACT;GACL;;;;;;;;EAsGO,gBAAgB,CACpB,OAAwC;IAExC,IAAI,IAAI,CAAC,eAAe,KAAK,OAAO,EAAE;MAClC,OAAO,IAAI,CAAC,eAAe,CAAC;KAC/B;IACD,IAAI,CAAC,eAAe,GAAG,OAAO,CAAC;IAC/B,OAAO,OAAO,CAAC;GAClB;EA8BO,WAAW;IACf,QAAQ,IAAI,CAAC,IAAI;MACb,KAAK,QAAQ,EAAE;QACX,OAAO,QAAQ,CAAC;OACnB;MACD,KAAK,OAAO,EAAE;QACV,OAAO,OAAO,CAAC;OAClB;MACD,KAAK,UAAU,EAAE;QACb,OAAO,UAAU,CAAC;OACrB;MACD,KAAK,UAAU,EAAE;QACb,OAAO,UAAU,CAAC;OACrB;MACD,SAAS;QACL,OAAO,UAAU,CAAC;OACrB;KACJ;GACJ;;;;;;","names":[],"sources":["./src/components/radio-button-group/radio-button.template.tsx","./src/components/list-item/list-item.scss?tag=limel-list-item","./src/components/list-item/list-item.tsx"],"sourcesContent":["import { FunctionalComponent, h } from '@stencil/core';\n\n/**\n * Radio Button Template\n *\n * This is a low-level template component that renders individual radio button elements\n * using Material Design Components (MDC) styling and structure. It's used internally\n * by the list component to render radio buttons when `type=\"radio\"` is specified.\n *\n * ## Usage in the Library\n *\n * This template is primarily used by:\n * - `limel-list` component when `type=\"radio\"`\n * - `limel-radio-button-group` component (which wraps `limel-list`)\n *\n * ## Why This Exists\n *\n * While we have `limel-radio-button-group` for most use cases, this template provides\n * the actual radio button HTML structure with proper MDC classes and accessibility\n * attributes. It ensures consistent styling and behavior across all radio button\n * implementations in the library.\n *\n * ## Design Philosophy\n *\n * This follows the principle that individual radio buttons should not be standalone\n * components, as a single radio button is never useful in a UI. Instead, this template\n * is used to build groups of radio buttons through higher-level components.\n *\n * @internal\n */\ninterface RadioButtonTemplateProps {\n disabled?: boolean;\n id: string;\n checked?: boolean;\n onChange?: (event: Event) => void;\n label?: string;\n}\n\nexport const RadioButtonTemplate: FunctionalComponent<\n RadioButtonTemplateProps\n> = (props) => {\n return (\n <div\n class={{\n 'boolean-input': true,\n 'radio-button': true,\n checked: props.checked,\n disabled: props.disabled,\n }}\n >\n <input\n type=\"radio\"\n id={props.id}\n checked={props.checked}\n disabled={props.disabled}\n onChange={props.onChange}\n />\n <div class=\"box\" />\n <label class=\"boolean-input-label\" htmlFor={props.id}>\n {props.label}\n </label>\n </div>\n );\n};\n","/**\n * @prop --notification-badge-text-color: (Publicly documented in `limel-menu` too) Defines the text color of notification badges. Defaults to `--color-white`.\n * @prop --notification-badge-background-color: (Publicly documented in `limel-menu` too) Defines the background color of notification badges. Defaults to `--color-red-default`.\n * @prop --limel-list-item-menu-order: Defines the order of the menu, within the list item's flexbox. Defaults to `3`.\n */\n\n@use '../../style/mixins';\n@forward '../checkbox/checkbox.scss';\n@forward '../radio-button-group/radio-button.scss';\n\n*,\n*:before,\n*:after {\n box-sizing: border-box;\n}\n\nlimel-list-item {\n min-height: 2.5rem;\n @include mixins.visualize-keyboard-focus();\n\n transition: background-color 0.6s ease;\n position: relative;\n isolation: isolate;\n\n display: flex;\n align-items: center;\n gap: 0.5rem;\n\n padding: 0 1rem;\n background-color: rgb(var(--contrast-100));\n\n &:hover {\n z-index: 1;\n transition: background-color 0.2s ease;\n border-radius: 0.5rem;\n }\n\n &:focus,\n &:focus-visible,\n &:active {\n z-index: 1;\n border-radius: 0.5rem;\n }\n\n &:first-of-type {\n border-top-left-radius: 0.5rem;\n border-top-right-radius: 0.5rem;\n }\n\n &:last-of-type {\n border-bottom-left-radius: 0.5rem;\n border-bottom-right-radius: 0.5rem;\n }\n\n &:not([disabled]):not([disabled='true']) {\n cursor: pointer;\n }\n\n &[disabled]:not([disabled='false']) {\n cursor: not-allowed;\n }\n}\n\nlimel-list-item[disabled]:not([disabled='false']) {\n cursor: not-allowed;\n\n .text,\n limel-icon,\n img,\n .boolean-input {\n opacity: 0.4;\n }\n}\n\nlimel-list-item:not([disabled]):not([disabled='true']):hover,\nlimel-list-item:not([disabled]):not([disabled='true']):focus-visible {\n background-color: rgb(var(--contrast-400));\n}\n\nlimel-list-item[type='option'] {\n &:before {\n transition: background-color 0.6s ease;\n content: '';\n position: absolute;\n inset: 0;\n\n opacity: 0.2;\n border-radius: 0.5rem;\n }\n\n &[selected]:not([selected='false']) {\n &:before {\n transition: background-color 0.2s ease;\n background-color: var(--limel-theme-primary-color);\n }\n }\n}\n\nlimel-list-item {\n .text {\n flex-grow: 1;\n min-width: 0;\n\n display: flex;\n flex-direction: column;\n\n padding: 0.5rem 0;\n\n color: var(--limel-theme-text-primary-on-background-color);\n }\n\n .label {\n @include mixins.truncate-text();\n\n font-size: var(--limel-theme-default-font-size);\n line-height: 1rem;\n }\n\n .description {\n @include mixins.truncate-text-on-line(var(--maxLinesSecondaryText));\n line-height: 1rem;\n font-size: var(--limel-theme-default-small-font-size);\n opacity: 0.6;\n }\n\n limel-icon {\n color: var(--limel-theme-text-secondary-on-background-color);\n flex-shrink: 0;\n margin-left: -0.5rem;\n\n &:has(+ img) {\n margin-left: 0;\n position: absolute;\n top: 0.125rem;\n left: 0.125rem;\n padding: 0.1875rem;\n width: 1.25rem;\n background-color: rgb(var(--contrast-200), 0.8);\n }\n }\n\n img {\n flex-shrink: 0;\n object-fit: cover;\n border-radius: 50%;\n width: 2rem;\n height: 2rem;\n box-shadow: 0 0 0 1px rgb(var(--contrast-800), 0.5);\n }\n\n limel-menu {\n margin-right: -0.5rem;\n // Sometimes, `primaryComponent`s in list items need to get\n // `order: 2;` to be placed after the text. But since the default `order`\n // of all lit item children is `0`, we need to push the menu to the far right\n // by giving it a bigger order number. Also, by making this into a variable\n // we can handle other edge-cases in consuming components.\n order: var(--limel-list-item-menu-order, 3);\n }\n}\n\nlimel-list-item {\n &[role='menuitem'] & {\n .label {\n font-size: var(--limel-theme-default-small-font-size);\n }\n }\n}\n\n// ====================\n// Checkbox and radios\n.boolean-input {\n width: var(--limel-boolean-input-box-size);\n margin-left: -0.25rem;\n &.checkbox {\n margin-right: 0.25rem;\n }\n\n limel-list-item:has(limel-icon) &,\n limel-list-item:has(img) & {\n margin-right: -0.25rem;\n margin-left: 0;\n order: 2;\n }\n}\n\n.boolean-input-label {\n @include mixins.truncate-text();\n opacity: 0;\n width: var(--limel-boolean-input-box-size);\n}\n// ====================\n","import { Component, Host, Prop, h } from '@stencil/core';\nimport { getIconName } from '../icon/get-icon-props';\nimport type { IconSize } from '../icon/icon.types';\nimport { createRandomString } from '../../util/random-string';\nimport { ListItem } from './list-item.types';\nimport { MenuItem } from '../menu/menu.types';\nimport { ListSeparator } from '../../global/shared-types/separator.types';\nimport { CheckboxTemplate } from '../checkbox/checkbox.template';\nimport { RadioButtonTemplate } from '../radio-button-group/radio-button.template';\nimport translate from '../../global/translations';\nimport { Languages } from '../date-picker/date.types';\n\n/**\n * This components displays the list item.\n * This centralizes styles and functionality, and helps reduce redundant code\n * in consumer components such as `limel-list` and `limel-menu-list`.\n *\n * :::note\n * The component has `shadow: false`. There are a few reasons for it:\n * 1. This is to improve performance, and ensure that its internal elements are\n * considered as internal parts of the consumer's DOM.\n * 2. The consumer does not need to implement the interactive styles\n * (such as `visualize-keyboard-focus` mixin) on their own. Since there is no\n * shadow DOM, our mixins can be applied directly to the `limel-list-item` elements,\n * within the component's own styles.\n * 3. Most importantly, the MDCList checks the light DOM of each list item\n * to find native inputs to decide the list mode (checkbox/radio).\n * With `shadow: true`, those inputs would be hidden inside the `limel-list-items`’s\n * shadow DOM, so MDC wouldn’t detect them and therefore throw errors, when given\n * an array index (for the items).\n * With `shadow: false`, the native `<input type=\"checkbox/radio\">` from this template\n * would be visible to MDC.\n * :::\n * @exampleComponent limel-example-list-item-basic\n * @exampleComponent limel-example-list-item-icon\n * @exampleComponent limel-example-list-item-icon-size\n * @exampleComponent limel-example-list-item-pictures\n * @exampleComponent limel-example-list-item-multiple-lines\n * @exampleComponent limel-example-list-item-interactive\n * @exampleComponent limel-example-list-item-radio\n * @exampleComponent limel-example-list-item-checkbox\n * @exampleComponent limel-example-list-item-actions\n * @exampleComponent limel-example-list-item-primary-component\n * @exampleComponent limel-example-list-item-command-text\n * @private\n */\n@Component({\n tag: 'limel-list-item',\n shadow: false,\n styleUrl: 'list-item.scss',\n})\nexport class ListItemComponent implements ListItem {\n /**\n * Defines the language for translations.\n * Will translate the translatable strings on the components.\n */\n @Prop({ reflect: true })\n public language: Languages = 'en';\n\n /**\n * {@inheritdoc ListItem.value}\n */\n @Prop()\n public value?: any;\n\n /**\n * {@inheritdoc ListItem.text}\n */\n @Prop({ reflect: true })\n public text: string;\n\n /**\n * {@inheritdoc ListItem.secondaryText}\n */\n @Prop({ reflect: true })\n public secondaryText?: string;\n\n /**\n * {@inheritdoc ListItem.disabled}\n */\n @Prop({ reflect: true })\n public disabled = false;\n\n /**\n * {@inheritdoc ListItem.icon}\n */\n @Prop()\n public icon?: string | ListItem['icon'];\n\n /**\n * Size of the icon displayed for this item.\n */\n @Prop({ reflect: true })\n public iconSize: IconSize = 'small';\n\n /**\n * Set to `true` if the list should display larger icons with a background\n */\n @Prop({ reflect: true })\n public badgeIcon = false;\n\n /**\n * {@inheritdoc ListItem.selected}\n */\n @Prop({ reflect: true })\n public selected = false;\n\n /**\n * {@inheritdoc ListItem.selected}\n */\n @Prop()\n public actions?: ListItem['actions'];\n\n /**\n * {@inheritdoc ListItem.selected}\n */\n @Prop()\n public primaryComponent?: ListItem['primaryComponent'];\n\n /**\n * {@inheritdoc ListItem.image}\n */\n @Prop()\n public image?: ListItem['image'];\n\n /**\n * The semantic role of the list item. This affects the ARIA role\n * and the interaction behavior.\n *\n * - 'option' → selectable via click/Enter/Space, aria-selected\n * - 'radio'/'checkbox' → selectable, aria-checked\n * - 'menuitem'/'listitem' → activation only, no selection toggle\n */\n @Prop({ reflect: true })\n public type: 'listitem' | 'menuitem' | 'option' | 'radio' | 'checkbox' =\n 'listitem';\n\n /**\n * Used to describe the list item for assistive technology.\n */\n private readonly descriptionId: string;\n\n /**\n * Used to label the list item for assistive technology.\n */\n private readonly labelId: string;\n\n // Memoized reference for the action items to avoid unnecessary updates\n private memoizedActions?: Array<MenuItem | ListSeparator>;\n\n constructor() {\n this.labelId = createRandomString();\n this.descriptionId = createRandomString();\n }\n\n public render() {\n const ariaProps: any = {\n 'aria-labelledby': this.labelId,\n 'aria-describedby': this.secondaryText\n ? this.descriptionId\n : undefined,\n 'aria-disabled': this.disabled ? 'true' : 'false',\n };\n\n // ARIA state depending on `role`/`type`\n if (this.type === 'radio' || this.type === 'checkbox') {\n ariaProps['aria-checked'] = this.selected ? 'true' : 'false';\n } else if (this.type === 'option' || this.type === 'menuitem') {\n // aria-selected for `option` (spec);\n // also keep for `menuitem` for visual state consistency\n ariaProps['aria-selected'] = this.selected ? 'true' : 'false';\n }\n\n return (\n <Host\n role={this.getHostRole()}\n class={{\n 'has-primary-component': !!this.primaryComponent?.name,\n }}\n {...ariaProps}\n >\n {this.renderRadioButton()}\n {this.renderCheckbox()}\n {this.renderIcon()}\n {this.renderImage()}\n {this.renderPrimaryComponent()}\n <div class=\"text\">\n {this.renderLabel()}\n {this.renderDescription()}\n </div>\n {this.renderActionMenu(this.actions)}\n </Host>\n );\n }\n\n private renderLabel = () => {\n return (\n <span class=\"label\" id={this.labelId}>\n {this.text}\n </span>\n );\n };\n\n private renderDescription = () => {\n if (!this.secondaryText) {\n return;\n }\n\n return (\n <span class=\"description\" id={this.descriptionId}>\n {this.secondaryText}\n </span>\n );\n };\n\n private renderIcon = () => {\n const iconName = getIconName(this.icon);\n if (!iconName) {\n return;\n }\n\n let iconColor: string | undefined;\n let iconBackgroundColor: string | undefined;\n let title: string | undefined;\n\n if (typeof this.icon === 'object') {\n iconColor = this.icon.color;\n iconBackgroundColor = this.icon.backgroundColor;\n title = this.icon.title;\n }\n\n const iconProps = {\n 'aria-label': title,\n 'aria-hidden': title ? null : 'true',\n name: iconName,\n style: {\n color: iconColor,\n 'background-color': iconBackgroundColor,\n },\n badge: this.badgeIcon,\n size: this.iconSize,\n };\n\n return <limel-icon {...iconProps} />;\n };\n\n private renderPrimaryComponent = () => {\n const primary = this.primaryComponent;\n if (!primary?.name) {\n return;\n }\n\n const PrimaryComponent: any = primary.name;\n const props = primary.props || {};\n\n return <PrimaryComponent {...props} />;\n };\n\n private renderImage = () => {\n if (!this.image) {\n return;\n }\n\n return <img src={this.image.src} alt={this.image.alt} loading=\"lazy\" />;\n };\n\n private renderActionMenu = (actions: Array<MenuItem | ListSeparator>) => {\n if (!actions || actions.length === 0) {\n return;\n }\n\n const stableActions = this.getStableActions(actions);\n return (\n <limel-menu\n class=\"mdc-deprecated-list-item__meta\"\n items={stableActions}\n openDirection=\"left-start\"\n >\n <limel-icon-button\n class=\"action-menu-trigger\"\n slot=\"trigger\"\n icon=\"menu_2\"\n label={this.actionMenuLabel()}\n />\n </limel-menu>\n );\n };\n\n /**\n * Returns a stable reference for the provided actions array to avoid\n * unnecessary re-renders of the action menu when the reference is unchanged.\n *\n * @param actions The actions (and separators) to display in the menu\n * @returns The same array instance that was previously seen, if unchanged\n */\n private getStableActions(\n actions: Array<MenuItem | ListSeparator>\n ): Array<MenuItem | ListSeparator> {\n if (this.memoizedActions === actions) {\n return this.memoizedActions;\n }\n this.memoizedActions = actions;\n return actions;\n }\n\n private renderRadioButton = () => {\n if (this.type !== 'radio') {\n return;\n }\n\n return (\n <RadioButtonTemplate\n id={`radio_${this.labelId}`}\n checked={this.selected}\n disabled={this.disabled}\n />\n );\n };\n\n private renderCheckbox = () => {\n if (this.type !== 'checkbox') {\n return;\n }\n\n return (\n <CheckboxTemplate\n id={`checkbox_${this.labelId}`}\n checked={this.selected}\n disabled={this.disabled}\n />\n );\n };\n\n private getHostRole(): string {\n switch (this.type) {\n case 'option': {\n return 'option';\n }\n case 'radio': {\n return 'radio';\n }\n case 'checkbox': {\n return 'checkbox';\n }\n case 'menuitem': {\n return 'menuitem';\n }\n default: {\n return 'listitem';\n }\n }\n }\n\n private actionMenuLabel = (): string => {\n return translate.get('file-viewer.more-actions', this.language);\n };\n}\n"],"version":3}
@@ -26188,9 +26188,14 @@ const getLinkDataAtPosition = (view, event) => {
26188
26188
  return { href: href, text: text, from: from, to: to };
26189
26189
  };
26190
26190
  const processModClickEvent = (view, event) => {
26191
- const { href } = getLinkDataAtPosition(view, event);
26191
+ const linkData = getLinkDataAtPosition(view, event);
26192
+ if (!linkData.href) {
26193
+ return false;
26194
+ }
26195
+ event.preventDefault();
26196
+ const { href } = linkData;
26192
26197
  if (href) {
26193
- window.open(href, '_blank');
26198
+ window.open(href, '_blank', 'noopener,noreferrer');
26194
26199
  return true;
26195
26200
  }
26196
26201
  return false;
@@ -26203,32 +26208,21 @@ const openLinkMenu = (view, href, text) => {
26203
26208
  });
26204
26209
  view.dom.dispatchEvent(event);
26205
26210
  };
26206
- let lastClickTime = 0;
26207
- const DOUBLE_CLICK_DELAY = 200;
26208
- let clickTimeout;
26209
- const processClickEvent = (view, event) => {
26210
- const now = Date.now();
26211
- if (now - lastClickTime < DOUBLE_CLICK_DELAY) {
26212
- clearTimeout(clickTimeout);
26213
- lastClickTime = now; // Reset lastClickTime to prevent single-click action
26211
+ const processDoubleClickEvent = (view, event) => {
26212
+ const linkData = getLinkDataAtPosition(view, event);
26213
+ if (!linkData) {
26214
26214
  return false;
26215
26215
  }
26216
- lastClickTime = now;
26217
- clickTimeout = setTimeout(() => {
26218
- const linkData = getLinkDataAtPosition(view, event);
26219
- if (linkData) {
26220
- const { href, text, from, to } = linkData;
26221
- const transaction = view.state.tr.setSelection(TextSelection.create(view.state.doc, from, to));
26222
- view.dispatch(transaction);
26223
- openLinkMenu(view, href, text);
26224
- }
26225
- }, DOUBLE_CLICK_DELAY);
26216
+ const { href, text, from, to } = linkData;
26217
+ const transaction = view.state.tr.setSelection(TextSelection.create(view.state.doc, from, to));
26218
+ view.dispatch(transaction);
26219
+ openLinkMenu(view, href, text);
26226
26220
  return true;
26227
26221
  };
26228
26222
  /**
26229
- * Regular expression for matching URLs, mailto links, and phone links
26223
+ * Regular expression for matching URLs, mailto links, phone links, and bare www-links
26230
26224
  */
26231
- const URL_REGEX = /(https?:\/\/[^\s<>"']+|mailto:[^\s<>"']+|tel:[^\s<>"']+)/g;
26225
+ const URL_REGEX = /(https?:\/\/[^\s<>"']+|mailto:[^\s<>"']+|tel:[^\s<>"']+|www\.[^\s<>"']+)/g;
26232
26226
  /**
26233
26227
  * Checks if the text contains any URLs, mailto links, or phone links
26234
26228
  * @param text
@@ -26252,8 +26246,19 @@ const createTextNode = (schema, content) => {
26252
26246
  * @param url
26253
26247
  */
26254
26248
  const createLinkNode = (schema, url) => {
26255
- const linkMark = schema.marks.link.create(getLinkAttributes(url, url));
26256
- return schema.text(url, [linkMark]);
26249
+ const normalizeUrlForLinkMark = (input) => {
26250
+ let output = input.trim();
26251
+ while (output.endsWith('\\')) {
26252
+ output = output.slice(0, -1);
26253
+ }
26254
+ if (output.toLowerCase().startsWith('www.')) {
26255
+ output = `https://${output}`;
26256
+ }
26257
+ return output;
26258
+ };
26259
+ const normalizedUrl = normalizeUrlForLinkMark(url);
26260
+ const linkMark = schema.marks.link.create(getLinkAttributes(normalizedUrl, normalizedUrl));
26261
+ return schema.text(normalizedUrl, [linkMark]);
26257
26262
  };
26258
26263
  /**
26259
26264
  * Finds all link matches in the provided text
@@ -26273,6 +26278,36 @@ const findLinkMatches = (text) => {
26273
26278
  }
26274
26279
  return matches;
26275
26280
  };
26281
+ /**
26282
+ * Creates nodes for the pasted text while preserving soft line breaks.
26283
+ * - Each newline becomes a `hard_break`.
26284
+ * - Empty lines are preserved (consecutive newlines => multiple `hard_break`s).
26285
+ * - URLs inside each line are converted to link-marked text.
26286
+ * @param text - Raw pasted text
26287
+ * @param schema - ProseMirror schema
26288
+ */
26289
+ const createNodesWithLinksAndBreaks = (text, schema) => {
26290
+ // Split preserves empty lines between consecutive newlines
26291
+ const lines = text.split(/\r\n|\r|\n/);
26292
+ const nodes = [];
26293
+ for (const [index, line] of lines.entries()) {
26294
+ if (line.length > 0) {
26295
+ nodes.push(...createNodesWithLinks(line, schema));
26296
+ }
26297
+ if (index < lines.length - 1) {
26298
+ const hb = schema.nodes.hard_break;
26299
+ if (hb) {
26300
+ nodes.push(hb.create());
26301
+ }
26302
+ else {
26303
+ // Fallback: if schema lacks hard_break, defer to default paste behavior
26304
+ // (Do NOT throw; keep behavior stable across versions)
26305
+ console.warn('hard_break node not found in schema');
26306
+ }
26307
+ }
26308
+ }
26309
+ return nodes;
26310
+ };
26276
26311
  /**
26277
26312
  * Creates text nodes with links for any URLs, mailto links, or phone links found in the text
26278
26313
  * @param text
@@ -26374,7 +26409,8 @@ const processPasteEvent$1 = (view, event) => {
26374
26409
  if (!text || !hasUrls(text)) {
26375
26410
  return false;
26376
26411
  }
26377
- const nodes = createNodesWithLinks(text, view.state.schema);
26412
+ const nodes = createNodesWithLinksAndBreaks(text, view.state.schema);
26413
+ event.preventDefault();
26378
26414
  pasteAsLink(view, nodes);
26379
26415
  return true;
26380
26416
  };
@@ -26391,11 +26427,12 @@ const createLinkPlugin = (updateLinkCallback) => {
26391
26427
  event.button === 0) {
26392
26428
  return processModClickEvent(view, event);
26393
26429
  }
26430
+ },
26431
+ dblclick: (view, event) => {
26394
26432
  if (event.button !== MouseButtons.Right) {
26395
26433
  // We want to ignore right-clicks
26396
- return processClickEvent(view, event);
26434
+ return processDoubleClickEvent(view, event);
26397
26435
  }
26398
- return true;
26399
26436
  },
26400
26437
  click: (_view, event) => {
26401
26438
  if (!(event.target instanceof HTMLElement)) {