@api-client/ui 0.4.5 → 0.5.1
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.
- package/build/src/elements/highlight/MarkedHighlight.d.ts.map +1 -1
- package/build/src/elements/highlight/MarkedHighlight.js +2 -1
- package/build/src/elements/highlight/MarkedHighlight.js.map +1 -1
- package/build/src/md/button/internals/base.js +1 -1
- package/build/src/md/button/internals/base.js.map +1 -1
- package/build/src/md/dialog/internals/Dialog.d.ts +18 -0
- package/build/src/md/dialog/internals/Dialog.d.ts.map +1 -1
- package/build/src/md/dialog/internals/Dialog.js +60 -2
- package/build/src/md/dialog/internals/Dialog.js.map +1 -1
- package/build/src/md/menu/internal/Menu.d.ts +1 -0
- package/build/src/md/menu/internal/Menu.d.ts.map +1 -1
- package/build/src/md/menu/internal/Menu.js +41 -1
- package/build/src/md/menu/internal/Menu.js.map +1 -1
- package/build/src/md/menu/internal/Menu.styles.d.ts.map +1 -1
- package/build/src/md/menu/internal/Menu.styles.js +4 -0
- package/build/src/md/menu/internal/Menu.styles.js.map +1 -1
- package/demo/md/dialog/dialog.ts +135 -1
- package/demo/md/menu/index.ts +216 -1
- package/package.json +2 -2
- package/src/elements/highlight/MarkedHighlight.ts +2 -1
- package/src/md/button/internals/base.ts +1 -1
- package/src/md/dialog/internals/Dialog.ts +54 -1
- package/src/md/menu/internal/Menu.styles.ts +4 -0
- package/src/md/menu/internal/Menu.ts +43 -1
- package/test/README.md +372 -0
- package/test/dom-assertions.test.ts +182 -0
- package/test/helpers/TestUtils.ts +243 -0
- package/test/helpers/UiMock.ts +83 -13
- package/test/md/dialog/UiDialog.test.ts +169 -0
- package/test/setup.test.ts +217 -0
- package/test/setup.ts +117 -0
|
@@ -104,10 +104,12 @@ let Menu = (() => {
|
|
|
104
104
|
this.open = !this.open;
|
|
105
105
|
this.ariaExpanded = String(this.open);
|
|
106
106
|
this.tabIndex = this.open ? 0 : -1;
|
|
107
|
+
const result = super.togglePopover(force);
|
|
107
108
|
if (this.open) {
|
|
109
|
+
this.positionMenu();
|
|
108
110
|
this.focus();
|
|
109
111
|
}
|
|
110
|
-
return
|
|
112
|
+
return result;
|
|
111
113
|
}
|
|
112
114
|
/**
|
|
113
115
|
* Shows the menu
|
|
@@ -117,6 +119,7 @@ let Menu = (() => {
|
|
|
117
119
|
this.ariaExpanded = 'true';
|
|
118
120
|
this.showPopover();
|
|
119
121
|
this.open = true;
|
|
122
|
+
this.positionMenu();
|
|
120
123
|
this.focus();
|
|
121
124
|
this.dispatchEvent(new CustomEvent('open', { bubbles: false, composed: true }));
|
|
122
125
|
}
|
|
@@ -131,6 +134,43 @@ let Menu = (() => {
|
|
|
131
134
|
this.closeSubMenu();
|
|
132
135
|
this.dispatchEvent(new CustomEvent('close', { bubbles: false, composed: true }));
|
|
133
136
|
}
|
|
137
|
+
positionMenu() {
|
|
138
|
+
// when there's more space above the anchor, position the menu above it
|
|
139
|
+
const box = this.getBoundingClientRect();
|
|
140
|
+
// Now, we determine, whether to position the menu above or below the anchor
|
|
141
|
+
// in a way, that if we have enough space below the anchor, we position it below,
|
|
142
|
+
// otherwise we position it above the anchor.
|
|
143
|
+
// our starting point is the anchor being positioned below the anchor
|
|
144
|
+
const menuBottom = box.top + box.height;
|
|
145
|
+
if (menuBottom <= innerHeight) {
|
|
146
|
+
// if the menu fits below the anchor, we leave it as is.
|
|
147
|
+
return;
|
|
148
|
+
}
|
|
149
|
+
// we do not make association from the menu to the anchor, so we make an assumption
|
|
150
|
+
// that the anchor is 40px high, which is the default height of a button.
|
|
151
|
+
// it can be different, but this is a good starting point.
|
|
152
|
+
const anchorHeight = 40;
|
|
153
|
+
const anchorBottom = box.top;
|
|
154
|
+
const anchorTop = anchorBottom - anchorHeight;
|
|
155
|
+
const menuHeight = box.height;
|
|
156
|
+
const spaceBelow = innerHeight - anchorBottom;
|
|
157
|
+
const spaceAbove = anchorTop;
|
|
158
|
+
const diffBelow = spaceBelow - menuHeight;
|
|
159
|
+
const diffAbove = spaceAbove - menuHeight;
|
|
160
|
+
// The initial check ensures the menu does not fit below. Now, check if it fits above.
|
|
161
|
+
if (diffAbove >= 0) {
|
|
162
|
+
this.style.setProperty('position-area', 'top span-right');
|
|
163
|
+
}
|
|
164
|
+
else if (diffAbove > diffBelow) {
|
|
165
|
+
// It doesn't fit in either direction. Choose the one with less overflow (larger, i.e., less negative, diff).
|
|
166
|
+
this.style.setProperty('position-area', 'top span-right');
|
|
167
|
+
this.style.maxHeight = `${spaceAbove}px`;
|
|
168
|
+
}
|
|
169
|
+
else {
|
|
170
|
+
this.style.setProperty('position-area', 'bottom span-right');
|
|
171
|
+
this.style.maxHeight = `${spaceBelow}px`;
|
|
172
|
+
}
|
|
173
|
+
}
|
|
134
174
|
/**
|
|
135
175
|
* Handles beforetoggle event from popover
|
|
136
176
|
*/
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"Menu.js","sourceRoot":"","sources":["../../../../../src/md/menu/internal/Menu.ts"],"names":[],"mappings":"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","sourcesContent":["import { html, PropertyValues, TemplateResult } from 'lit'\nimport { property, state, queryAssignedElements } from 'lit/decorators.js'\nimport { classMap } from 'lit/directives/class-map.js'\nimport { nanoid } from 'nanoid'\nimport UiList from '../../list/internals/List.js'\nimport UiMenuItem from './MenuItem.js'\nimport UiSubMenu from './SubMenu.js'\nimport { setDisabled } from '../../../lib/disabled.js'\nimport UiListItem from '../../list/internals/ListItem.js'\nimport { bound } from '../../../decorators/bound.js'\n\n/**\n * Material Design 3 Menu component with sub-menu support.\n * Uses Popover API and Anchor Positioning API for modern positioning.\n *\n * @fires select - Dispatched when a menu item is selected\n * @fires close - Dispatched when the menu is closed\n */\nexport default class Menu extends UiList {\n /**\n * Whether the menu is currently open\n * @attribute\n */\n @property({ type: Boolean, reflect: true }) accessor open = false\n\n /**\n * Whether the menu is disabled\n * @attribute\n */\n @property({ type: Boolean, reflect: true }) accessor disabled = false\n\n /**\n * Currently active sub-menu\n */\n @state() accessor activeSubMenu: UiSubMenu | null = null\n\n /**\n * Assigned menu items from light DOM\n */\n @queryAssignedElements({ selector: 'ui-menu-item' }) protected accessor assignedMenuItems!: UiMenuItem[]\n\n constructor() {\n super()\n this.selector = 'ui-menu-item'\n this.ariaExpanded = 'false'\n this.addEventListener('beforetoggle', this.handleBeforeToggle.bind(this))\n }\n\n override connectedCallback(): void {\n super.connectedCallback()\n this.setAttribute('role', 'menu')\n this.setAttribute('tabindex', '-1')\n if (!this.hasAttribute('popover')) {\n this.setAttribute('popover', 'auto')\n }\n if (!this.id) {\n this.id = nanoid()\n }\n }\n\n protected override updated(changedProperties: PropertyValues<this>): void {\n super.updated(changedProperties)\n\n if (changedProperties.has('disabled')) {\n setDisabled(this, this.disabled)\n }\n }\n\n override togglePopover(force?: boolean): boolean {\n this.open = !this.open\n this.ariaExpanded = String(this.open)\n this.tabIndex = this.open ? 0 : -1\n if (this.open) {\n this.focus()\n }\n return super.togglePopover(force)\n }\n\n /**\n * Shows the menu\n */\n show(): void {\n this.tabIndex = 0 // Make menu focusable\n this.ariaExpanded = 'true'\n this.showPopover()\n this.open = true\n this.focus()\n this.dispatchEvent(new CustomEvent('open', { bubbles: false, composed: true }))\n }\n\n /**\n * Hides the menu\n */\n hide(): void {\n this.tabIndex = -1\n this.ariaExpanded = 'false'\n this.hidePopover()\n this.open = false\n this.closeSubMenu()\n this.dispatchEvent(new CustomEvent('close', { bubbles: false, composed: true }))\n }\n\n /**\n * Handles beforetoggle event from popover\n */\n protected handleBeforeToggle(e: Event): void {\n const toggleEvent = e as ToggleEvent\n if (toggleEvent.newState === 'closed') {\n this.open = false\n this.closeSubMenu()\n }\n }\n\n /**\n * Handles keyboard navigation for the menu\n */\n override handleKeydown(e: KeyboardEvent): void {\n if (!this.open || e.defaultPrevented) return\n\n switch (e.key) {\n case 'Escape':\n e.preventDefault()\n this.hide()\n break\n case 'ArrowRight':\n e.preventDefault()\n this.openSubMenu()\n break\n case 'ArrowLeft':\n e.preventDefault()\n this.closeSubMenu()\n break\n default:\n // Let the parent UiList handle other keys\n super.handleKeydown(e)\n }\n }\n\n @bound\n handleSubMenuSelect(e: CustomEvent): void {\n super.notifySelect(e.detail.item, e.detail.index)\n }\n\n /**\n * Opens the sub-menu for the currently active item\n */\n protected openSubMenu(): void {\n const activeItem = this.activeListItem as UiMenuItem\n if (activeItem?.hasSubMenu) {\n activeItem.openSubMenu()\n }\n }\n\n /**\n * Closes the currently open sub-menu\n */\n closeSubMenu(): void {\n if (this.activeSubMenu) {\n this.activeSubMenu.removeEventListener('select', this.handleSubMenuSelect as EventListener)\n this.activeSubMenu.hide()\n this.activeSubMenu = null\n }\n }\n\n /**\n * Sets the active sub-menu\n */\n setActiveSubMenu(subMenu: UiSubMenu | null): void {\n this.activeSubMenu = subMenu\n subMenu?.addEventListener('select', this.handleSubMenuSelect as EventListener)\n }\n\n override notifySelect(item: UiListItem, index?: number): boolean {\n this.hide()\n return super.notifySelect(item, index)\n }\n\n /**\n * Handles sub-menu opening\n */\n protected handleSubMenuOpen(e: CustomEvent): void {\n const subMenu = e.detail.subMenu\n this.setActiveSubMenu(subMenu)\n }\n\n /**\n * Handles slot changes to update menu items\n */\n protected handleSlotChange(): void {\n // Update the items list when slot content changes\n this.updateItems()\n }\n\n override render(): TemplateResult {\n const classes = classMap({\n 'menu-container': true,\n })\n\n return html`\n <div class=${classes}>\n <slot @slotchange=${this.handleSlotChange}></slot>\n </div>\n `\n }\n}\n"]}
|
|
1
|
+
{"version":3,"file":"Menu.js","sourceRoot":"","sources":["../../../../../src/md/menu/internal/Menu.ts"],"names":[],"mappings":"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","sourcesContent":["import { html, PropertyValues, TemplateResult } from 'lit'\nimport { property, state, queryAssignedElements } from 'lit/decorators.js'\nimport { classMap } from 'lit/directives/class-map.js'\nimport { nanoid } from 'nanoid'\nimport UiList from '../../list/internals/List.js'\nimport UiMenuItem from './MenuItem.js'\nimport UiSubMenu from './SubMenu.js'\nimport { setDisabled } from '../../../lib/disabled.js'\nimport UiListItem from '../../list/internals/ListItem.js'\nimport { bound } from '../../../decorators/bound.js'\n\n/**\n * Material Design 3 Menu component with sub-menu support.\n * Uses Popover API and Anchor Positioning API for modern positioning.\n *\n * @fires select - Dispatched when a menu item is selected\n * @fires close - Dispatched when the menu is closed\n */\nexport default class Menu extends UiList {\n /**\n * Whether the menu is currently open\n * @attribute\n */\n @property({ type: Boolean, reflect: true }) accessor open = false\n\n /**\n * Whether the menu is disabled\n * @attribute\n */\n @property({ type: Boolean, reflect: true }) accessor disabled = false\n\n /**\n * Currently active sub-menu\n */\n @state() accessor activeSubMenu: UiSubMenu | null = null\n\n /**\n * Assigned menu items from light DOM\n */\n @queryAssignedElements({ selector: 'ui-menu-item' }) protected accessor assignedMenuItems!: UiMenuItem[]\n\n constructor() {\n super()\n this.selector = 'ui-menu-item'\n this.ariaExpanded = 'false'\n this.addEventListener('beforetoggle', this.handleBeforeToggle.bind(this))\n }\n\n override connectedCallback(): void {\n super.connectedCallback()\n this.setAttribute('role', 'menu')\n this.setAttribute('tabindex', '-1')\n if (!this.hasAttribute('popover')) {\n this.setAttribute('popover', 'auto')\n }\n if (!this.id) {\n this.id = nanoid()\n }\n }\n\n protected override updated(changedProperties: PropertyValues<this>): void {\n super.updated(changedProperties)\n\n if (changedProperties.has('disabled')) {\n setDisabled(this, this.disabled)\n }\n }\n\n override togglePopover(force?: boolean): boolean {\n this.open = !this.open\n this.ariaExpanded = String(this.open)\n this.tabIndex = this.open ? 0 : -1\n const result = super.togglePopover(force)\n if (this.open) {\n this.positionMenu()\n this.focus()\n }\n return result\n }\n\n /**\n * Shows the menu\n */\n show(): void {\n this.tabIndex = 0 // Make menu focusable\n this.ariaExpanded = 'true'\n this.showPopover()\n this.open = true\n this.positionMenu()\n this.focus()\n this.dispatchEvent(new CustomEvent('open', { bubbles: false, composed: true }))\n }\n\n /**\n * Hides the menu\n */\n hide(): void {\n this.tabIndex = -1\n this.ariaExpanded = 'false'\n this.hidePopover()\n this.open = false\n this.closeSubMenu()\n this.dispatchEvent(new CustomEvent('close', { bubbles: false, composed: true }))\n }\n\n positionMenu(): void {\n // when there's more space above the anchor, position the menu above it\n const box = this.getBoundingClientRect()\n // Now, we determine, whether to position the menu above or below the anchor\n // in a way, that if we have enough space below the anchor, we position it below,\n // otherwise we position it above the anchor.\n\n // our starting point is the anchor being positioned below the anchor\n const menuBottom = box.top + box.height\n if (menuBottom <= innerHeight) {\n // if the menu fits below the anchor, we leave it as is.\n return\n }\n // we do not make association from the menu to the anchor, so we make an assumption\n // that the anchor is 40px high, which is the default height of a button.\n // it can be different, but this is a good starting point.\n const anchorHeight = 40\n const anchorBottom = box.top\n const anchorTop = anchorBottom - anchorHeight\n const menuHeight = box.height\n\n const spaceBelow = innerHeight - anchorBottom\n const spaceAbove = anchorTop\n\n const diffBelow = spaceBelow - menuHeight\n const diffAbove = spaceAbove - menuHeight\n // The initial check ensures the menu does not fit below. Now, check if it fits above.\n if (diffAbove >= 0) {\n this.style.setProperty('position-area', 'top span-right')\n } else if (diffAbove > diffBelow) {\n // It doesn't fit in either direction. Choose the one with less overflow (larger, i.e., less negative, diff).\n this.style.setProperty('position-area', 'top span-right')\n this.style.maxHeight = `${spaceAbove}px`\n } else {\n this.style.setProperty('position-area', 'bottom span-right')\n this.style.maxHeight = `${spaceBelow}px`\n }\n }\n\n /**\n * Handles beforetoggle event from popover\n */\n protected handleBeforeToggle(e: Event): void {\n const toggleEvent = e as ToggleEvent\n if (toggleEvent.newState === 'closed') {\n this.open = false\n this.closeSubMenu()\n }\n }\n\n /**\n * Handles keyboard navigation for the menu\n */\n override handleKeydown(e: KeyboardEvent): void {\n if (!this.open || e.defaultPrevented) return\n\n switch (e.key) {\n case 'Escape':\n e.preventDefault()\n this.hide()\n break\n case 'ArrowRight':\n e.preventDefault()\n this.openSubMenu()\n break\n case 'ArrowLeft':\n e.preventDefault()\n this.closeSubMenu()\n break\n default:\n // Let the parent UiList handle other keys\n super.handleKeydown(e)\n }\n }\n\n @bound\n handleSubMenuSelect(e: CustomEvent): void {\n super.notifySelect(e.detail.item, e.detail.index)\n }\n\n /**\n * Opens the sub-menu for the currently active item\n */\n protected openSubMenu(): void {\n const activeItem = this.activeListItem as UiMenuItem\n if (activeItem?.hasSubMenu) {\n activeItem.openSubMenu()\n }\n }\n\n /**\n * Closes the currently open sub-menu\n */\n closeSubMenu(): void {\n if (this.activeSubMenu) {\n this.activeSubMenu.removeEventListener('select', this.handleSubMenuSelect as EventListener)\n this.activeSubMenu.hide()\n this.activeSubMenu = null\n }\n }\n\n /**\n * Sets the active sub-menu\n */\n setActiveSubMenu(subMenu: UiSubMenu | null): void {\n this.activeSubMenu = subMenu\n subMenu?.addEventListener('select', this.handleSubMenuSelect as EventListener)\n }\n\n override notifySelect(item: UiListItem, index?: number): boolean {\n this.hide()\n return super.notifySelect(item, index)\n }\n\n /**\n * Handles sub-menu opening\n */\n protected handleSubMenuOpen(e: CustomEvent): void {\n const subMenu = e.detail.subMenu\n this.setActiveSubMenu(subMenu)\n }\n\n /**\n * Handles slot changes to update menu items\n */\n protected handleSlotChange(): void {\n // Update the items list when slot content changes\n this.updateItems()\n }\n\n override render(): TemplateResult {\n const classes = classMap({\n 'menu-container': true,\n })\n\n return html`\n <div class=${classes}>\n <slot @slotchange=${this.handleSlotChange}></slot>\n </div>\n `\n }\n}\n"]}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"Menu.styles.d.ts","sourceRoot":"","sources":["../../../../../src/md/menu/internal/Menu.styles.ts"],"names":[],"mappings":";AAEA,
|
|
1
|
+
{"version":3,"file":"Menu.styles.d.ts","sourceRoot":"","sources":["../../../../../src/md/menu/internal/Menu.styles.ts"],"names":[],"mappings":";AAEA,wBA0LC"}
|
|
@@ -8,6 +8,10 @@ export default css `
|
|
|
8
8
|
margin: 0;
|
|
9
9
|
padding: 0;
|
|
10
10
|
border: none;
|
|
11
|
+
overflow: hidden;
|
|
12
|
+
/* in most cases the max-height won't matter as this assumes the whole screen to be available, which is rarely the truth. */
|
|
13
|
+
max-height: 90vh;
|
|
14
|
+
overflow: auto;
|
|
11
15
|
}
|
|
12
16
|
|
|
13
17
|
:host(:popover-open) {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"Menu.styles.js","sourceRoot":"","sources":["../../../../../src/md/menu/internal/Menu.styles.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,GAAG,EAAE,MAAM,KAAK,CAAA;AAEzB,eAAe,GAAG,CAAA
|
|
1
|
+
{"version":3,"file":"Menu.styles.js","sourceRoot":"","sources":["../../../../../src/md/menu/internal/Menu.styles.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,GAAG,EAAE,MAAM,KAAK,CAAA;AAEzB,eAAe,GAAG,CAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;CA0LjB,CAAA","sourcesContent":["import { css } from 'lit'\n\nexport default css`\n :host {\n display: none;\n position-area: bottom span-right;\n position-try: normal flip-block;\n position: absolute;\n margin: 0;\n padding: 0;\n border: none;\n overflow: hidden;\n /* in most cases the max-height won't matter as this assumes the whole screen to be available, which is rarely the truth. */\n max-height: 90vh;\n overflow: auto;\n }\n\n :host(:popover-open) {\n display: block;\n background-color: var(--md-sys-color-surface);\n border-radius: var(--md-sys-shape-corner-extra-small);\n box-shadow: var(--md-sys-elevation-3);\n }\n\n .menu-container {\n min-width: 200px;\n padding: 8px 0;\n outline: none;\n }\n\n .menu-divider {\n height: 1px;\n background-color: var(--md-sys-color-outline-variant);\n margin: 8px 0;\n }\n\n /* Menu Item Styles */\n .menu-item {\n position: relative;\n display: flex;\n align-items: center;\n min-height: 48px;\n padding: 0 16px;\n cursor: pointer;\n outline: none;\n transition: background-color 0.2s ease;\n }\n\n .menu-item:hover {\n background-color: var(--md-sys-color-surface-variant);\n }\n\n .menu-item:focus {\n background-color: var(--md-sys-color-surface-variant);\n }\n\n .menu-item[disabled] {\n opacity: 0.38;\n cursor: not-allowed;\n pointer-events: none;\n }\n\n .menu-item-content {\n display: flex;\n align-items: center;\n width: 100%;\n gap: 12px;\n }\n\n .menu-item-icon {\n display: flex;\n align-items: center;\n justify-content: center;\n width: 24px;\n height: 24px;\n color: var(--md-sys-color-on-surface);\n font-size: 20px;\n }\n\n .menu-item-label {\n flex: 1;\n color: var(--md-sys-color-on-surface);\n font-family: var(--md-sys-typescale-label-large-font-family-name);\n font-size: var(--md-sys-typescale-label-large-font-size);\n font-weight: var(--md-sys-typescale-label-large-font-weight);\n line-height: var(--md-sys-typescale-label-large-line-height);\n letter-spacing: var(--md-sys-typescale-label-large-letter-spacing);\n }\n\n .menu-item-arrow {\n display: flex;\n align-items: center;\n justify-content: center;\n width: 24px;\n height: 24px;\n color: var(--md-sys-color-on-surface);\n font-size: 18px;\n font-weight: 500;\n }\n\n .menu-item-with-submenu {\n position: relative;\n }\n\n .menu-item-with-submenu:hover .menu-item-arrow {\n color: var(--md-sys-color-primary);\n }\n\n /* Sub-menu Styles */\n .submenu-container {\n min-width: 200px;\n max-width: 320px;\n background-color: var(--md-sys-color-surface);\n border-radius: var(--md-sys-shape-corner-extra-small);\n box-shadow: var(--md-sys-elevation-level3);\n padding: 8px 0;\n }\n\n /* Submenu positioning with Anchor API */\n ui-sub-menu {\n display: none;\n }\n\n ui-sub-menu:popover-open {\n display: block;\n background-color: var(--md-sys-color-surface);\n border-radius: var(--md-sys-shape-corner-extra-small);\n box-shadow: var(--md-sys-elevation-level3);\n min-width: 200px;\n max-width: 320px;\n padding: 8px 0;\n z-index: 1000;\n }\n\n /* Fallback positioning for browsers without anchor positioning */\n @supports not (anchor-name: --test) {\n ui-sub-menu:popover-open {\n position: fixed;\n transform: translateX(200px);\n }\n }\n\n /* Focus Ring */\n md-focus-ring {\n --md-focus-ring-color: var(--md-sys-color-primary);\n --md-focus-ring-width: 2px;\n }\n\n /* Ripple Effect */\n ui-ripple {\n --md-ripple-color: var(--md-sys-color-primary);\n --md-ripple-opacity: 0.12;\n }\n\n /* Responsive Design */\n @media (max-width: 600px) {\n .menu-container {\n min-width: 180px;\n max-width: 280px;\n }\n\n .submenu-container {\n min-width: 180px;\n max-width: 280px;\n }\n }\n\n /* High Contrast Mode */\n @media (prefers-contrast: high) {\n .menu-container {\n border: 1px solid var(--md-sys-color-outline);\n }\n\n .submenu-container {\n border: 1px solid var(--md-sys-color-outline);\n }\n\n .menu-divider {\n background-color: var(--md-sys-color-outline);\n }\n }\n\n /* Reduced Motion */\n @media (prefers-reduced-motion: reduce) {\n .menu-item {\n transition: none;\n }\n }\n`\n"]}
|
package/demo/md/dialog/dialog.ts
CHANGED
|
@@ -18,6 +18,8 @@ class ComponentDemoPage extends DemoPage {
|
|
|
18
18
|
|
|
19
19
|
@reactive() accessor overflowOpened = false
|
|
20
20
|
|
|
21
|
+
@reactive() accessor formOpened = false
|
|
22
|
+
|
|
21
23
|
protected openSimple(): void {
|
|
22
24
|
this.simpleOpened = true
|
|
23
25
|
}
|
|
@@ -45,6 +47,15 @@ class ComponentDemoPage extends DemoPage {
|
|
|
45
47
|
this.reportClosingReason(e.detail)
|
|
46
48
|
}
|
|
47
49
|
|
|
50
|
+
protected openForm(): void {
|
|
51
|
+
this.formOpened = true
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
protected formClosed(e: CustomEvent<UiDialogClosingReason>): void {
|
|
55
|
+
this.formOpened = false
|
|
56
|
+
this.reportClosingReason(e.detail)
|
|
57
|
+
}
|
|
58
|
+
|
|
48
59
|
imperativeDialog: UiDialog | null = null
|
|
49
60
|
|
|
50
61
|
protected openImperative(): void {
|
|
@@ -81,7 +92,8 @@ class ComponentDemoPage extends DemoPage {
|
|
|
81
92
|
contentTemplate(): TemplateResult {
|
|
82
93
|
return html`
|
|
83
94
|
<a href="../">Back</a>
|
|
84
|
-
${this.simpleDialog()} ${this.fullDialog()} ${this.overflowDialog()} ${this.
|
|
95
|
+
${this.simpleDialog()} ${this.fullDialog()} ${this.overflowDialog()} ${this.formDialog()}
|
|
96
|
+
${this.renderImperativeDialog()}
|
|
85
97
|
`
|
|
86
98
|
}
|
|
87
99
|
|
|
@@ -244,6 +256,128 @@ class ComponentDemoPage extends DemoPage {
|
|
|
244
256
|
`
|
|
245
257
|
}
|
|
246
258
|
|
|
259
|
+
formDialog(): TemplateResult {
|
|
260
|
+
return html`
|
|
261
|
+
<section class="demo-section">
|
|
262
|
+
<h2 class="title-large">Form dialog</h2>
|
|
263
|
+
<p>This dialog contains a form with validation and submit handling.</p>
|
|
264
|
+
<ui-button color="filled" @click="${this.openForm}">Open Form Dialog</ui-button>
|
|
265
|
+
<form @submit="${this.handleFormSubmit}" style="display: contents;">
|
|
266
|
+
<ui-dialog
|
|
267
|
+
?open="${this.formOpened}"
|
|
268
|
+
@close="${this.formClosed}"
|
|
269
|
+
modal
|
|
270
|
+
style="--ui-dialog-max-width: 500px;"
|
|
271
|
+
submitClose
|
|
272
|
+
>
|
|
273
|
+
<ui-icon slot="icon" icon="info"></ui-icon>
|
|
274
|
+
<span slot="title">User Registration</span>
|
|
275
|
+
|
|
276
|
+
<div style="display: flex; flex-direction: column; gap: 16px;">
|
|
277
|
+
<label style="display: flex; flex-direction: column; gap: 4px;">
|
|
278
|
+
<span style="font-weight: 500; color: var(--md-sys-color-on-surface);">Full Name *</span>
|
|
279
|
+
<input
|
|
280
|
+
type="text"
|
|
281
|
+
name="fullName"
|
|
282
|
+
required
|
|
283
|
+
style="padding: 12px; border: 1px solid var(--md-sys-color-outline); border-radius: 4px; font-size: 14px;"
|
|
284
|
+
placeholder="Enter your full name"
|
|
285
|
+
/>
|
|
286
|
+
</label>
|
|
287
|
+
|
|
288
|
+
<label style="display: flex; flex-direction: column; gap: 4px;">
|
|
289
|
+
<span style="font-weight: 500; color: var(--md-sys-color-on-surface);">Email *</span>
|
|
290
|
+
<input
|
|
291
|
+
type="email"
|
|
292
|
+
name="email"
|
|
293
|
+
required
|
|
294
|
+
style="padding: 12px; border: 1px solid var(--md-sys-color-outline); border-radius: 4px; font-size: 14px;"
|
|
295
|
+
placeholder="Enter your email address"
|
|
296
|
+
/>
|
|
297
|
+
</label>
|
|
298
|
+
|
|
299
|
+
<label style="display: flex; flex-direction: column; gap: 4px;">
|
|
300
|
+
<span style="font-weight: 500; color: var(--md-sys-color-on-surface);">Phone Number</span>
|
|
301
|
+
<input
|
|
302
|
+
type="tel"
|
|
303
|
+
name="phone"
|
|
304
|
+
style="padding: 12px; border: 1px solid var(--md-sys-color-outline); border-radius: 4px; font-size: 14px;"
|
|
305
|
+
placeholder="Enter your phone number (optional)"
|
|
306
|
+
/>
|
|
307
|
+
</label>
|
|
308
|
+
|
|
309
|
+
<label style="display: flex; flex-direction: column; gap: 4px;">
|
|
310
|
+
<span style="font-weight: 500; color: var(--md-sys-color-on-surface);">Department</span>
|
|
311
|
+
<select
|
|
312
|
+
name="department"
|
|
313
|
+
style="padding: 12px; border: 1px solid var(--md-sys-color-outline); border-radius: 4px; font-size: 14px; background: white;"
|
|
314
|
+
>
|
|
315
|
+
<option value="">Select a department</option>
|
|
316
|
+
<option value="engineering">Engineering</option>
|
|
317
|
+
<option value="design">Design</option>
|
|
318
|
+
<option value="marketing">Marketing</option>
|
|
319
|
+
<option value="sales">Sales</option>
|
|
320
|
+
<option value="support">Support</option>
|
|
321
|
+
</select>
|
|
322
|
+
</label>
|
|
323
|
+
|
|
324
|
+
<label style="display: flex; align-items: center; gap: 8px; margin-top: 8px;">
|
|
325
|
+
<input type="checkbox" name="newsletter" style="margin: 0;" />
|
|
326
|
+
<span style="font-size: 14px; color: var(--md-sys-color-on-surface);">
|
|
327
|
+
Subscribe to our newsletter
|
|
328
|
+
</span>
|
|
329
|
+
</label>
|
|
330
|
+
|
|
331
|
+
<label style="display: flex; align-items: center; gap: 8px;">
|
|
332
|
+
<input type="checkbox" name="terms" required style="margin: 0;" />
|
|
333
|
+
<span style="font-size: 14px; color: var(--md-sys-color-on-surface);">
|
|
334
|
+
I agree to the <a href="#" style="color: var(--md-sys-color-primary);">Terms and Conditions</a> *
|
|
335
|
+
</span>
|
|
336
|
+
</label>
|
|
337
|
+
</div>
|
|
338
|
+
|
|
339
|
+
<ui-button color="text" slot="button" value="dismiss">Cancel</ui-button>
|
|
340
|
+
<ui-button color="filled" slot="button" value="confirm" type="submit">Register</ui-button>
|
|
341
|
+
</ui-dialog>
|
|
342
|
+
</form>
|
|
343
|
+
</section>
|
|
344
|
+
`
|
|
345
|
+
}
|
|
346
|
+
|
|
347
|
+
protected handleFormSubmit(e: CustomEvent): void {
|
|
348
|
+
e.preventDefault()
|
|
349
|
+
|
|
350
|
+
// Get form data from the event
|
|
351
|
+
const form = e.target as HTMLFormElement
|
|
352
|
+
const formData = new FormData(form)
|
|
353
|
+
|
|
354
|
+
// Convert to regular object for easier handling
|
|
355
|
+
const data: Record<string, string | boolean> = {}
|
|
356
|
+
for (const [key, value] of formData.entries()) {
|
|
357
|
+
if (key === 'newsletter' || key === 'terms') {
|
|
358
|
+
data[key] = value === 'on'
|
|
359
|
+
} else {
|
|
360
|
+
data[key] = value as string
|
|
361
|
+
}
|
|
362
|
+
}
|
|
363
|
+
|
|
364
|
+
console.log('Form submitted with data:', data)
|
|
365
|
+
|
|
366
|
+
// Simulate form validation
|
|
367
|
+
if (!data.fullName || !data.email) {
|
|
368
|
+
console.error('Required fields are missing')
|
|
369
|
+
return
|
|
370
|
+
}
|
|
371
|
+
|
|
372
|
+
if (!data.terms) {
|
|
373
|
+
console.error('Terms and conditions must be accepted')
|
|
374
|
+
return
|
|
375
|
+
}
|
|
376
|
+
|
|
377
|
+
// If validation passes, the dialog will close automatically
|
|
378
|
+
console.log('Registration successful!', data)
|
|
379
|
+
}
|
|
380
|
+
|
|
247
381
|
renderImperativeDialog(): TemplateResult {
|
|
248
382
|
return html`
|
|
249
383
|
<section class="demo-section">
|
package/demo/md/menu/index.ts
CHANGED
|
@@ -15,6 +15,8 @@ class ComponentDemoPage extends DemoPage {
|
|
|
15
15
|
@reactive() accessor basicCount = 0
|
|
16
16
|
@reactive() accessor nestedMenuOutput = ''
|
|
17
17
|
@reactive() accessor nestedCount = 0
|
|
18
|
+
@reactive() accessor overflowMenuOutput = ''
|
|
19
|
+
@reactive() accessor overflowCount = 0
|
|
18
20
|
|
|
19
21
|
handleBasicMenuSelect(e: CustomEvent): void {
|
|
20
22
|
const item = e.detail.item as HTMLElement
|
|
@@ -30,8 +32,15 @@ class ComponentDemoPage extends DemoPage {
|
|
|
30
32
|
this.nestedCount++
|
|
31
33
|
}
|
|
32
34
|
|
|
35
|
+
handleOverflowMenuSelect(e: CustomEvent): void {
|
|
36
|
+
const item = e.detail.item as HTMLElement
|
|
37
|
+
const index = e.detail.index
|
|
38
|
+
this.overflowMenuOutput = `Selected item: ${item.textContent}, Index: ${index}`
|
|
39
|
+
this.overflowCount++
|
|
40
|
+
}
|
|
41
|
+
|
|
33
42
|
contentTemplate(): TemplateResult {
|
|
34
|
-
const { basicMenuOutput, nestedMenuOutput, nestedCount, basicCount } = this
|
|
43
|
+
const { basicMenuOutput, nestedMenuOutput, nestedCount, basicCount, overflowMenuOutput, overflowCount } = this
|
|
35
44
|
return html`
|
|
36
45
|
<a href="../">Back</a>
|
|
37
46
|
|
|
@@ -68,6 +77,212 @@ class ComponentDemoPage extends DemoPage {
|
|
|
68
77
|
: ''}
|
|
69
78
|
</section>
|
|
70
79
|
|
|
80
|
+
<section class="demo-section">
|
|
81
|
+
<h2 class="title-large">Overflow Menu</h2>
|
|
82
|
+
<p>A menu with many items that will overflow and require scrolling:</p>
|
|
83
|
+
<ui-button id="overflow-menu-trigger" color="filled" popovertarget="overflow-menu"
|
|
84
|
+
>Open Overflow Menu</ui-button
|
|
85
|
+
>
|
|
86
|
+
<ui-menu id="overflow-menu" popover="auto" @select="${this.handleOverflowMenuSelect}">
|
|
87
|
+
<ui-menu-item>
|
|
88
|
+
<span slot="start"><ui-icon>home</ui-icon></span>
|
|
89
|
+
<span>Home</span>
|
|
90
|
+
</ui-menu-item>
|
|
91
|
+
<ui-menu-item>
|
|
92
|
+
<span slot="start"><ui-icon>account_circle</ui-icon></span>
|
|
93
|
+
<span>Profile</span>
|
|
94
|
+
</ui-menu-item>
|
|
95
|
+
<ui-menu-item>
|
|
96
|
+
<span slot="start"><ui-icon>settings</ui-icon></span>
|
|
97
|
+
<span>Settings</span>
|
|
98
|
+
</ui-menu-item>
|
|
99
|
+
<ui-menu-item>
|
|
100
|
+
<span slot="start"><ui-icon>notifications</ui-icon></span>
|
|
101
|
+
<span>Notifications</span>
|
|
102
|
+
</ui-menu-item>
|
|
103
|
+
<ui-menu-item>
|
|
104
|
+
<span slot="start"><ui-icon>mail</ui-icon></span>
|
|
105
|
+
<span>Messages</span>
|
|
106
|
+
</ui-menu-item>
|
|
107
|
+
<ui-menu-item>
|
|
108
|
+
<span slot="start"><ui-icon>favorite</ui-icon></span>
|
|
109
|
+
<span>Favorites</span>
|
|
110
|
+
</ui-menu-item>
|
|
111
|
+
<ui-menu-item>
|
|
112
|
+
<span slot="start"><ui-icon>bookmark</ui-icon></span>
|
|
113
|
+
<span>Bookmarks</span>
|
|
114
|
+
</ui-menu-item>
|
|
115
|
+
<ui-menu-item>
|
|
116
|
+
<span slot="start"><ui-icon>history</ui-icon></span>
|
|
117
|
+
<span>History</span>
|
|
118
|
+
</ui-menu-item>
|
|
119
|
+
<ui-menu-item>
|
|
120
|
+
<span slot="start"><ui-icon>download</ui-icon></span>
|
|
121
|
+
<span>Downloads</span>
|
|
122
|
+
</ui-menu-item>
|
|
123
|
+
<ui-menu-item>
|
|
124
|
+
<span slot="start"><ui-icon>cloud</ui-icon></span>
|
|
125
|
+
<span>Cloud Storage</span>
|
|
126
|
+
</ui-menu-item>
|
|
127
|
+
<ui-menu-item>
|
|
128
|
+
<span slot="start"><ui-icon>share</ui-icon></span>
|
|
129
|
+
<span>Share</span>
|
|
130
|
+
</ui-menu-item>
|
|
131
|
+
<ui-menu-item>
|
|
132
|
+
<span slot="start"><ui-icon>security</ui-icon></span>
|
|
133
|
+
<span>Security</span>
|
|
134
|
+
</ui-menu-item>
|
|
135
|
+
<ui-menu-item>
|
|
136
|
+
<span slot="start"><ui-icon>backup</ui-icon></span>
|
|
137
|
+
<span>Backup</span>
|
|
138
|
+
</ui-menu-item>
|
|
139
|
+
<ui-menu-item>
|
|
140
|
+
<span slot="start"><ui-icon>sync</ui-icon></span>
|
|
141
|
+
<span>Sync</span>
|
|
142
|
+
</ui-menu-item>
|
|
143
|
+
<ui-menu-item>
|
|
144
|
+
<span slot="start"><ui-icon>account_box</ui-icon></span>
|
|
145
|
+
<span>Account Management</span>
|
|
146
|
+
</ui-menu-item>
|
|
147
|
+
<ui-menu-item>
|
|
148
|
+
<span slot="start"><ui-icon>payment</ui-icon></span>
|
|
149
|
+
<span>Payment Methods</span>
|
|
150
|
+
</ui-menu-item>
|
|
151
|
+
<ui-menu-item>
|
|
152
|
+
<span slot="start"><ui-icon>credit_card</ui-icon></span>
|
|
153
|
+
<span>Billing</span>
|
|
154
|
+
</ui-menu-item>
|
|
155
|
+
<ui-menu-item>
|
|
156
|
+
<span slot="start"><ui-icon>receipt</ui-icon></span>
|
|
157
|
+
<span>Receipts</span>
|
|
158
|
+
</ui-menu-item>
|
|
159
|
+
<ui-menu-item>
|
|
160
|
+
<span slot="start"><ui-icon>analytics</ui-icon></span>
|
|
161
|
+
<span>Analytics</span>
|
|
162
|
+
</ui-menu-item>
|
|
163
|
+
<ui-menu-item>
|
|
164
|
+
<span slot="start"><ui-icon>insights</ui-icon></span>
|
|
165
|
+
<span>Insights</span>
|
|
166
|
+
</ui-menu-item>
|
|
167
|
+
<ui-menu-item>
|
|
168
|
+
<span slot="start"><ui-icon>trending_up</ui-icon></span>
|
|
169
|
+
<span>Trends</span>
|
|
170
|
+
</ui-menu-item>
|
|
171
|
+
<ui-menu-item>
|
|
172
|
+
<span slot="start"><ui-icon>dashboard</ui-icon></span>
|
|
173
|
+
<span>Dashboard</span>
|
|
174
|
+
</ui-menu-item>
|
|
175
|
+
<ui-menu-item>
|
|
176
|
+
<span slot="start"><ui-icon>widgets</ui-icon></span>
|
|
177
|
+
<span>Widgets</span>
|
|
178
|
+
</ui-menu-item>
|
|
179
|
+
<ui-menu-item>
|
|
180
|
+
<span slot="start"><ui-icon>extension</ui-icon></span>
|
|
181
|
+
<span>Extensions</span>
|
|
182
|
+
</ui-menu-item>
|
|
183
|
+
<ui-menu-item>
|
|
184
|
+
<span slot="start"><ui-icon>apps</ui-icon></span>
|
|
185
|
+
<span>Applications</span>
|
|
186
|
+
</ui-menu-item>
|
|
187
|
+
<ui-menu-item>
|
|
188
|
+
<span slot="start"><ui-icon>devices</ui-icon></span>
|
|
189
|
+
<span>Devices</span>
|
|
190
|
+
</ui-menu-item>
|
|
191
|
+
<ui-menu-item>
|
|
192
|
+
<span slot="start"><ui-icon>network_check</ui-icon></span>
|
|
193
|
+
<span>Network Status</span>
|
|
194
|
+
</ui-menu-item>
|
|
195
|
+
<ui-menu-item>
|
|
196
|
+
<span slot="start"><ui-icon>wifi</ui-icon></span>
|
|
197
|
+
<span>Wi-Fi Settings</span>
|
|
198
|
+
</ui-menu-item>
|
|
199
|
+
<ui-menu-item>
|
|
200
|
+
<span slot="start"><ui-icon>bluetooth</ui-icon></span>
|
|
201
|
+
<span>Bluetooth</span>
|
|
202
|
+
</ui-menu-item>
|
|
203
|
+
<ui-menu-item>
|
|
204
|
+
<span slot="start"><ui-icon>location_on</ui-icon></span>
|
|
205
|
+
<span>Location Services</span>
|
|
206
|
+
</ui-menu-item>
|
|
207
|
+
<ui-menu-item>
|
|
208
|
+
<span slot="start"><ui-icon>language</ui-icon></span>
|
|
209
|
+
<span>Language</span>
|
|
210
|
+
</ui-menu-item>
|
|
211
|
+
<ui-menu-item>
|
|
212
|
+
<span slot="start"><ui-icon>accessibility</ui-icon></span>
|
|
213
|
+
<span>Accessibility</span>
|
|
214
|
+
</ui-menu-item>
|
|
215
|
+
<ui-menu-item>
|
|
216
|
+
<span slot="start"><ui-icon>brightness_6</ui-icon></span>
|
|
217
|
+
<span>Display</span>
|
|
218
|
+
</ui-menu-item>
|
|
219
|
+
<ui-menu-item>
|
|
220
|
+
<span slot="start"><ui-icon>volume_up</ui-icon></span>
|
|
221
|
+
<span>Sound</span>
|
|
222
|
+
</ui-menu-item>
|
|
223
|
+
<ui-menu-item>
|
|
224
|
+
<span slot="start"><ui-icon>battery_std</ui-icon></span>
|
|
225
|
+
<span>Battery</span>
|
|
226
|
+
</ui-menu-item>
|
|
227
|
+
<ui-menu-item>
|
|
228
|
+
<span slot="start"><ui-icon>storage</ui-icon></span>
|
|
229
|
+
<span>Storage</span>
|
|
230
|
+
</ui-menu-item>
|
|
231
|
+
<ui-menu-item>
|
|
232
|
+
<span slot="start"><ui-icon>memory</ui-icon></span>
|
|
233
|
+
<span>Memory</span>
|
|
234
|
+
</ui-menu-item>
|
|
235
|
+
<ui-menu-item>
|
|
236
|
+
<span slot="start"><ui-icon>update</ui-icon></span>
|
|
237
|
+
<span>Software Update</span>
|
|
238
|
+
</ui-menu-item>
|
|
239
|
+
<ui-menu-item>
|
|
240
|
+
<span slot="start"><ui-icon>info</ui-icon></span>
|
|
241
|
+
<span>About</span>
|
|
242
|
+
</ui-menu-item>
|
|
243
|
+
<ui-menu-item>
|
|
244
|
+
<span slot="start"><ui-icon>help</ui-icon></span>
|
|
245
|
+
<span>Help & Support</span>
|
|
246
|
+
</ui-menu-item>
|
|
247
|
+
<ui-menu-item>
|
|
248
|
+
<span slot="start"><ui-icon>feedback</ui-icon></span>
|
|
249
|
+
<span>Send Feedback</span>
|
|
250
|
+
</ui-menu-item>
|
|
251
|
+
<ui-menu-item>
|
|
252
|
+
<span slot="start"><ui-icon>bug_report</ui-icon></span>
|
|
253
|
+
<span>Report Bug</span>
|
|
254
|
+
</ui-menu-item>
|
|
255
|
+
<ui-menu-item>
|
|
256
|
+
<span slot="start"><ui-icon>contact_support</ui-icon></span>
|
|
257
|
+
<span>Contact Support</span>
|
|
258
|
+
</ui-menu-item>
|
|
259
|
+
<ui-menu-item>
|
|
260
|
+
<span slot="start"><ui-icon>forum</ui-icon></span>
|
|
261
|
+
<span>Community Forum</span>
|
|
262
|
+
</ui-menu-item>
|
|
263
|
+
<ui-menu-item>
|
|
264
|
+
<span slot="start"><ui-icon>school</ui-icon></span>
|
|
265
|
+
<span>Learning Center</span>
|
|
266
|
+
</ui-menu-item>
|
|
267
|
+
<ui-menu-item>
|
|
268
|
+
<span slot="start"><ui-icon>library_books</ui-icon></span>
|
|
269
|
+
<span>Documentation</span>
|
|
270
|
+
</ui-menu-item>
|
|
271
|
+
<ui-menu-item>
|
|
272
|
+
<span slot="start"><ui-icon>video_library</ui-icon></span>
|
|
273
|
+
<span>Video Tutorials</span>
|
|
274
|
+
</ui-menu-item>
|
|
275
|
+
<ui-menu-item>
|
|
276
|
+
<span slot="start"><ui-icon>logout</ui-icon></span>
|
|
277
|
+
<span>Sign Out</span>
|
|
278
|
+
</ui-menu-item>
|
|
279
|
+
</ui-menu>
|
|
280
|
+
${overflowMenuOutput
|
|
281
|
+
? html`<p>${overflowMenuOutput}</p>
|
|
282
|
+
<p>Count: ${overflowCount}</p>`
|
|
283
|
+
: ''}
|
|
284
|
+
</section>
|
|
285
|
+
|
|
71
286
|
<section class="demo-section">
|
|
72
287
|
<h2 class="title-large">Submenus</h2>
|
|
73
288
|
<p>A menu with submenus:</p>
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@api-client/ui",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.5.1",
|
|
4
4
|
"description": "Internal UI component library for the API Client ecosystem.",
|
|
5
5
|
"license": "UNLICENSED",
|
|
6
6
|
"main": "build/src/index.js",
|
|
@@ -182,7 +182,7 @@
|
|
|
182
182
|
"dompurify": "^3.2.5",
|
|
183
183
|
"idb-keyval": "^6.1.0",
|
|
184
184
|
"lit": "^3.2.1",
|
|
185
|
-
"marked": "^
|
|
185
|
+
"marked": "^16.0.0",
|
|
186
186
|
"monaco-editor": "^0.52.2",
|
|
187
187
|
"nanoid": "^5.1.5",
|
|
188
188
|
"prismjs": "^1.28.0",
|
|
@@ -247,7 +247,8 @@ export default class MarkedHighlight extends LitElement {
|
|
|
247
247
|
pedantic: this.pedantic,
|
|
248
248
|
gfm: true,
|
|
249
249
|
}
|
|
250
|
-
|
|
250
|
+
// eslint-disable-next-line no-misleading-character-class
|
|
251
|
+
let out = marked(data.replace(/^[\u200B\u200C\u200D\u200E\u200F\uFEFF]/, ''), opts) as string
|
|
251
252
|
if (this.sanitize) {
|
|
252
253
|
if (this.sanitizer) {
|
|
253
254
|
out = this.sanitizer(out)
|
|
@@ -240,7 +240,7 @@ export default class BaseButton extends UiElement {
|
|
|
240
240
|
}
|
|
241
241
|
|
|
242
242
|
override handleClick(e: MouseEvent): void {
|
|
243
|
-
super.handleClick(
|
|
243
|
+
// Do not call super.handleClick() here, as it would call `endPress` again.
|
|
244
244
|
if (this.disabled) {
|
|
245
245
|
e.preventDefault()
|
|
246
246
|
e.stopPropagation()
|