@api-client/ui 0.2.5 → 0.2.6
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/autocomplete/internals/autocomplete.d.ts.map +1 -1
- package/build/src/elements/autocomplete/internals/autocomplete.js +13 -16
- package/build/src/elements/autocomplete/internals/autocomplete.js.map +1 -1
- package/build/src/elements/highlight/MarkedHighlight.d.ts +2 -1
- package/build/src/elements/highlight/MarkedHighlight.d.ts.map +1 -1
- package/build/src/elements/highlight/MarkedHighlight.js +14 -11
- package/build/src/elements/highlight/MarkedHighlight.js.map +1 -1
- package/package.json +1 -1
- package/src/elements/autocomplete/internals/autocomplete.ts +13 -18
- package/src/elements/highlight/MarkedHighlight.ts +16 -13
- package/test/elements/autocomplete/autocomplete-input.spec.ts +8 -6
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"autocomplete.d.ts","sourceRoot":"","sources":["../../../../../src/elements/autocomplete/internals/autocomplete.ts"],"names":[],"mappings":"AAAA,OAAO,EAAQ,UAAU,EAAE,cAAc,EAAE,cAAc,EAAE,MAAM,KAAK,CAAA;AAEtE,OAAO,KAAK,SAAS,MAAM,0CAA0C,CAAA;AAIrE;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA+GG;AACH,MAAM,CAAC,OAAO,OAAO,YAAa,SAAQ,UAAU;cAC/B,gBAAgB,IAAI,WAAW,GAAG,gBAAgB;IAIrE;;OAEG;IACH,SAAS,CAAC,QAAQ,CAAC,EAAE,gBAAgB,CAAA;IAErC;;;OAGG;IACM,SAAS,CAAC,QAAQ,CAAC,OAAO,SAAK;IAExC;;;;;;;;;;;OAWG;IACS,QAAQ,CAAC,YAAY,EAAE,QAAQ,GAAG,KAAK,CAAW;IAE9D;;;OAGG;IACH,SAAS,CAAC,QAAQ,CAAC,EAAE,gBAAgB,GAAG,WAAW,GAAG,IAAI,CAAA;IAC1D;;;OAGG;IACH,SAAS,CAAC,cAAc,CAAC,EAAE,SAAS,GAAG,IAAI,CAAA;IAE3C;;OAEG;IACH,IAAI,MAAM,IAAI,OAAO,CAEpB;IAEQ,iBAAiB,IAAI,IAAI;
|
|
1
|
+
{"version":3,"file":"autocomplete.d.ts","sourceRoot":"","sources":["../../../../../src/elements/autocomplete/internals/autocomplete.ts"],"names":[],"mappings":"AAAA,OAAO,EAAQ,UAAU,EAAE,cAAc,EAAE,cAAc,EAAE,MAAM,KAAK,CAAA;AAEtE,OAAO,KAAK,SAAS,MAAM,0CAA0C,CAAA;AAIrE;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA+GG;AACH,MAAM,CAAC,OAAO,OAAO,YAAa,SAAQ,UAAU;cAC/B,gBAAgB,IAAI,WAAW,GAAG,gBAAgB;IAIrE;;OAEG;IACH,SAAS,CAAC,QAAQ,CAAC,EAAE,gBAAgB,CAAA;IAErC;;;OAGG;IACM,SAAS,CAAC,QAAQ,CAAC,OAAO,SAAK;IAExC;;;;;;;;;;;OAWG;IACS,QAAQ,CAAC,YAAY,EAAE,QAAQ,GAAG,KAAK,CAAW;IAE9D;;;OAGG;IACH,SAAS,CAAC,QAAQ,CAAC,EAAE,gBAAgB,GAAG,WAAW,GAAG,IAAI,CAAA;IAC1D;;;OAGG;IACH,SAAS,CAAC,cAAc,CAAC,EAAE,SAAS,GAAG,IAAI,CAAA;IAE3C;;OAEG;IACH,IAAI,MAAM,IAAI,OAAO,CAEpB;IAEQ,iBAAiB,IAAI,IAAI;IAUzB,oBAAoB,IAAI,IAAI;cAQlB,YAAY,CAAC,EAAE,EAAE,cAAc,GAAG,IAAI;IAKzD;;;OAGG;IACG,UAAU,IAAI,OAAO,CAAC,IAAI,CAAC;IAYjC;;;;OAIG;IACH,SAAS,CAAC,eAAe,CAAC,SAAS,EAAE,cAAc,EAAE,GAAG,IAAI;IAyB5D;;OAEG;IACH,SAAS,CAAC,mBAAmB,IAAI,IAAI;IAUrC;;OAEG;IACH,SAAS,CAAC,yBAAyB,IAAI,IAAI;IAY3C;;;;OAIG;IACH,SAAS,CAAC,UAAU,CAAC,KAAK,EAAE,WAAW,GAAG,IAAI;IAoB9C;;;;OAIG;IACH,SAAS,CAAC,gBAAgB,CAAC,kBAAkB,EAAE,SAAS,GAAG,IAAI;IAe/D;;;OAGG;IAEH,SAAS,CAAC,gBAAgB,IAAI,IAAI;IAalC;;;;OAIG;IAEH,SAAS,CAAC,WAAW,CAAC,KAAK,EAAE,KAAK,GAAG,IAAI;IAMzC;;;;;;OAMG;IAEH,SAAS,CAAC,aAAa,CAAC,KAAK,EAAE,aAAa,GAAG,IAAI;IA4BnD;;;OAGG;IACH,SAAS,CAAC,YAAY,CAAC,GAAG,EAAE,MAAM,GAAG,IAAI;IAazC;;;OAGG;IAEH,SAAS,CAAC,eAAe,IAAI,IAAI;IAajC;;;;OAIG;IAEH,SAAS,CAAC,sBAAsB,CAAC,KAAK,EAAE,WAAW,GAAG,IAAI;IAa1D;;;OAGG;IAEH,SAAS,CAAC,2BAA2B,IAAI,IAAI;IAS7C;;OAEG;IACH,SAAS,CAAC,eAAe,IAAI,IAAI;IAcjC;;;;;;;;;;;;OAYG;IACH,SAAS,CAAC,kBAAkB,CAAC,OAAO,EAAE,WAAW,EAAE,MAAM,EAAE,WAAW,GAAG,KAAK,GAAG,QAAQ;IAuBzF;;OAEG;IACH,SAAS,CAAC,gBAAgB,IAAI,IAAI;IAMlC;;;;OAIG;IACH,SAAS,CAAC,iBAAiB,CAAC,KAAK,EAAE,MAAM,GAAG,IAAI;cA6C7B,MAAM,IAAI,cAAc;CAuC5C"}
|
|
@@ -108,6 +108,7 @@ let Autocomplete = (() => {
|
|
|
108
108
|
if (!this.id) {
|
|
109
109
|
this.id = `autocomplete-${Math.random().toString(36).substring(2, 15)}`;
|
|
110
110
|
}
|
|
111
|
+
this.classList.add(this.id);
|
|
111
112
|
}
|
|
112
113
|
disconnectedCallback() {
|
|
113
114
|
super.disconnectedCallback();
|
|
@@ -215,11 +216,6 @@ let Autocomplete = (() => {
|
|
|
215
216
|
this.inputRef.addEventListener('input', this.handleInput);
|
|
216
217
|
this.inputRef.addEventListener('keydown', this.handleKeydown);
|
|
217
218
|
this.inputRef.addEventListener('blur', this.handleInputBlur);
|
|
218
|
-
// Apply initial filtering if suggestions are already present
|
|
219
|
-
if (this.suggestionsRef) {
|
|
220
|
-
this.suggestionsRef.style.setProperty('position-anchor', `--${this.inputId}`);
|
|
221
|
-
this.filterSuggestions(this.inputRef.value || '');
|
|
222
|
-
}
|
|
223
219
|
}
|
|
224
220
|
/**
|
|
225
221
|
* Sets up the slotted suggestions element (assumed to be a `UiListbox`).
|
|
@@ -231,9 +227,6 @@ let Autocomplete = (() => {
|
|
|
231
227
|
this.suggestionsRef = suggestionsElement;
|
|
232
228
|
this.suggestionsRef.popover = 'manual';
|
|
233
229
|
this.suggestionsRef.tabIndex = -1; // Prevent direct focus
|
|
234
|
-
if (this.inputId) {
|
|
235
|
-
this.suggestionsRef.style.setProperty('position-anchor', `--${this.inputId}`);
|
|
236
|
-
}
|
|
237
230
|
this.suggestionsRef.addEventListener('select', this.handleSuggestionSelect);
|
|
238
231
|
// The `List` dispatches `itemschange` when the slot changes, so we can listen to it.
|
|
239
232
|
this.suggestionsRef.addEventListener('itemschange', this.handleSuggestionsSlotChange);
|
|
@@ -467,31 +460,35 @@ let Autocomplete = (() => {
|
|
|
467
460
|
}
|
|
468
461
|
}
|
|
469
462
|
render() {
|
|
470
|
-
const { id, positionArea } = this;
|
|
463
|
+
const { id, positionArea, inputId } = this;
|
|
464
|
+
/*
|
|
465
|
+
position-try-fallbacks:
|
|
466
|
+
flip-block,
|
|
467
|
+
flip-inline,
|
|
468
|
+
flip-block flip-inline;
|
|
469
|
+
*/
|
|
471
470
|
return html `
|
|
472
471
|
<style>
|
|
473
|
-
|
|
472
|
+
.${id} {
|
|
474
473
|
display: inline-block;
|
|
475
474
|
|
|
476
475
|
[popover] {
|
|
477
476
|
border: none;
|
|
478
477
|
margin: 0;
|
|
479
|
-
position-area: ${positionArea};
|
|
480
|
-
position-try-fallbacks:
|
|
481
|
-
flip-block,
|
|
482
|
-
flip-inline,
|
|
483
|
-
flip-block flip-inline;
|
|
484
|
-
width: anchor-size(width);
|
|
485
478
|
|
|
486
479
|
box-shadow: var(--md-sys-elevation-1);
|
|
487
480
|
border-radius: var(--md-sys-shape-corner-medium);
|
|
488
481
|
|
|
482
|
+
position-area: ${positionArea};
|
|
483
|
+
position-anchor: --${inputId};
|
|
484
|
+
|
|
489
485
|
overflow: auto;
|
|
490
486
|
/* We try 100% and then vendor options which are more accurate */
|
|
491
487
|
height: 100%;
|
|
492
488
|
height: -webkit-fill-available;
|
|
493
489
|
height: -moz-available;
|
|
494
490
|
max-height: max-content;
|
|
491
|
+
width: anchor-size(width);
|
|
495
492
|
}
|
|
496
493
|
|
|
497
494
|
[popover]:not(:popover-open) {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"autocomplete.js","sourceRoot":"","sources":["../../../../../src/elements/autocomplete/internals/autocomplete.ts"],"names":[],"mappings":"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","sourcesContent":["import { html, LitElement, PropertyValues, TemplateResult } from 'lit'\nimport { property, state } from 'lit/decorators.js'\nimport type UiListbox from '../../../md/listbox/internals/Listbox.js'\nimport type UiListItem from '../../../md/list/internals/ListItem.js'\nimport { bound } from '../../../decorators/bound.js'\n\n/**\n * An accessible and performant autocomplete component that enhances a text input with a list of suggestions.\n *\n * The `autocomplete-input` component provides a flexible way to add autocomplete functionality\n * to any text input. It works by coordinating a slotted input element with a slotted `ui-listbox`\n * containing suggestions.\n *\n * Key Features:\n *\n * - **Popover Management**: Automatically shows and hides the suggestions popover based on input focus\n * and user interaction.\n * - **Keyboard Navigation**: Allows users to navigate suggestions using ArrowUp, ArrowDown keys directly\n * from the input. Enter selects a suggestion, and Escape closes the popover.\n * The suggestion list itself never gains focus.\n * - **Dynamic Filtering**: Filters the list of suggestions as the user types into the input. Items not matching\n * the query are hidden (not removed).\n * - By default, filtering checks `item.dataset.value` and then `item.textContent`.\n * - If a `ui-list-item` has a `data-index` attribute (e.g., `data-index=\"name email\"`), filtering will search\n * within the specified `data-*` attributes (e.g., `data-name`, `data-email`).\n * - **Mutation Awareness**: Reacts to changes in slotted suggestions, re-filtering them if necessary.\n * - **Event-Driven**: Notifies the application via an `autocomplete` event when a suggestion is selected.\n * The component itself does not modify the input's value, giving the application author full control.\n *\n * ### Accessibility\n *\n * The `autocomplete-input` component is designed with accessibility at its core:\n * - **Keyboard Navigation**: Full keyboard support for navigating suggestions (ArrowUp, ArrowDown),\n * selecting (Enter), and closing (Escape), all while focus remains on the input field.\n * - **ARIA Attributes**: While the `autocomplete-input` manages ARIA attributes related to the popover's\n * state, the slotted `ui-listbox` is responsible for its internal ARIA roles and states\n * (e.g., `role=\"listbox\"`, `aria-activedescendant`).\n * - **Labeling Suggestions**: It is **crucial** for accessibility that the slotted `ui-listbox`\n * has an `aria-label` attribute. This provides a descriptive name for the list of suggestions,\n * which is announced by screen readers.\n *\n * The component uses CSS anchor positioning to place the suggestions popover relative to the input.\n * Ensure your `ui-listbox` is styled appropriately for popover display (e.g., `popover=\"manual\"`, `position-anchor`).\n * The component will manage `showPopover()` and `hidePopover()` calls.\n *\n * @slot input - The input element that will be used for autocomplete. This element should be an `HTMLInputElement`\n * or behave like one (have a `value` property and dispatch `input`, `focus`, `blur`, and `keydown`\n * events).\n * @slot suggestions - The `ui-listbox` element containing `ui-list-item` elements as suggestions.\n * @slot anchor - An optional element that points to element that will be used as the anchor for the popover.\n * This is useful if you want to position the suggestions relative to a different element than the input.\n * If not provided, the input element will be used as the anchor.\n * @slot Any additional content that should be rendered inside the component.\n *\n * @fires autocomplete - Dispatched when a suggestion is selected by the user (e.g., via click or Enter key).\n * The `event.detail` object contains:\n * - `item`: The selected `UiListItem` instance.\n *\n * @example\n * ```html\n * <autocomplete-input @autocomplete=\"${this.handleAutocompleteSelection}\">\n * <input slot=\"input\" type=\"text\" placeholder=\"Search fruits...\" />\n * <ui-listbox slot=\"suggestions\">\n * <ui-list-item data-value=\"apple\">Apple</ui-list-item>\n * <ui-list-item data-value=\"banana\">Banana</ui-list-item>\n * <ui-list-item data-value=\"cherry\">Cherry</ui-list-item>\n * </ui-listbox>\n * <!-- With aria-label for accessibility -->\n * <ui-listbox slot=\"suggestions\" aria-label=\"Fruit suggestions\">\n * <ui-list-item data-value=\"apple\">Apple</ui-list-item>\n * <ui-list-item data-value=\"banana\">Banana</ui-list-item>\n * <ui-list-item data-value=\"cherry\">Cherry</ui-list-item>\n * </ui-listbox>\n * </autocomplete-input>\n *\n * <script>\n * // In your component/script\n * handleAutocompleteSelection(event) {\n * const selectedItem = event.detail.item;\n * const inputElement = this.shadowRoot.querySelector('input[slot=\"input\"]');\n * if (inputElement) {\n * inputElement.value = selectedItem.dataset.value || selectedItem.textContent;\n * }\n * console.log('Selected:', selectedItem.dataset.value);\n * }\n * </script>\n * ```\n *\n * @example Dynamic filtering with `data-index`\n * ```html\n * <autocomplete-input @autocomplete=\"${this.handleUserSelection}\">\n * <input slot=\"input\" type=\"text\" placeholder=\"Search users...\" />\n * <ui-listbox slot=\"suggestions\" aria-label=\"User suggestions\">\n * <ui-list-item data-id=\"1\" data-name=\"Alice Wonderland\" data-email=\"alice@example.com\" data-index=\"name email\">\n * Alice Wonderland\n * <span slot=\"supporting-text\">alice@example.com</span>\n * </ui-list-item>\n * <ui-list-item data-id=\"2\" data-name=\"Bob The Builder\" data-email=\"bob@example.com\" data-index=\"name email\">\n * Bob The Builder\n * <span slot=\"supporting-text\">bob@example.com</span>\n * </ui-list-item>\n * </ui-listbox>\n * </autocomplete-input>\n *\n * <script>\n * // In your component/script\n * handleUserSelection(event) {\n * const selectedItem = event.detail.item;\n * const inputElement = this.shadowRoot.querySelector('input[slot=\"input\"]');\n * if (inputElement) {\n * // You might want to display the name, but store the ID\n * inputElement.value = selectedItem.dataset.name;\n * }\n * console.log('Selected user ID:', selectedItem.dataset.id);\n * }\n * </script>\n * ```\n */\nexport default class Autocomplete extends LitElement {\n protected override createRenderRoot(): HTMLElement | DocumentFragment {\n return this\n }\n\n /**\n * The MutationObserver instance used to watch for changes in slotted children.\n */\n protected observer?: MutationObserver\n\n /**\n * The ID of the input element, generated if not provided.\n * This is used for CSS anchoring and to ensure unique IDs for accessibility.\n */\n @state() protected accessor inputId = ''\n\n /**\n * The position area for the suggestions popover.\n * This can be 'bottom' or 'top', depending on available space.\n * Default is 'bottom'.\n *\n * Note, this is set dynamically based on available space\n * and the position of the input element. This only sets the initial value.\n *\n * @attribute\n * @type {'bottom' | 'top'}\n * @default 'bottom'\n */\n @property() accessor positionArea: 'bottom' | 'top' = 'bottom'\n\n /**\n * The reference to the slotted input element.\n * This should be an `HTMLInputElement` or behave like one.\n */\n protected inputRef?: HTMLInputElement | HTMLElement | null\n /**\n * The reference to the slotted suggestions element, which should be a `ui-listbox`.\n * This is used to manage the suggestions popover and filtering.\n */\n protected suggestionsRef?: UiListbox | null\n\n /**\n * Checks if the suggestions popover is currently open.\n */\n get opened(): boolean {\n return this.suggestionsRef?.matches(':popover-open') || false\n }\n\n override connectedCallback(): void {\n super.connectedCallback()\n this.observer = new MutationObserver(this.handleMutations.bind(this))\n this.observer.observe(this, { childList: true })\n if (!this.id) {\n this.id = `autocomplete-${Math.random().toString(36).substring(2, 15)}`\n }\n }\n\n override disconnectedCallback(): void {\n super.disconnectedCallback()\n this.observer?.disconnect()\n this.observer = undefined\n this.clearInputListeners()\n this.clearSuggestionsListeners()\n }\n\n protected override firstUpdated(cp: PropertyValues): void {\n super.firstUpdated(cp)\n this.firstSetup()\n }\n\n /**\n * Performs initial setup after the first update, ensuring that slotted input\n * and suggestions elements are configured.\n */\n async firstSetup(): Promise<void> {\n await this.updateComplete\n const input = this.querySelector('[slot=\"input\"]') as HTMLElement | null\n const suggestions = this.querySelector('[slot=\"suggestions\"]') as HTMLElement | null\n if (input) {\n this.setupInput(input)\n }\n if (suggestions) {\n this.setupSuggestions(suggestions as UiListbox)\n }\n }\n\n /**\n * Handles mutations observed on the component's slotted children.\n * This is used to set up or tear down input and suggestions elements when they are added or removed.\n * @param mutations An array of MutationRecord objects.\n */\n protected handleMutations(mutations: MutationRecord[]): void {\n for (const mutation of mutations) {\n if (mutation.type === 'childList') {\n for (const node of mutation.removedNodes) {\n if (node instanceof HTMLElement) {\n if (node.slot === 'input' && this.inputRef === node) {\n this.clearInputListeners()\n } else if (node.slot === 'suggestions' && this.suggestionsRef === node) {\n this.clearSuggestionsListeners()\n }\n }\n }\n for (const node of mutation.addedNodes) {\n if (node instanceof HTMLElement) {\n if (node.slot === 'input') {\n this.setupInput(node)\n } else if (node.slot === 'suggestions') {\n this.setupSuggestions(node as UiListbox)\n }\n }\n }\n }\n }\n }\n\n /**\n * Clears event listeners from the current input reference and resets it.\n */\n protected clearInputListeners(): void {\n if (this.inputRef) {\n this.inputRef.removeEventListener('focus', this.handleInputFocus)\n this.inputRef.removeEventListener('input', this.handleInput)\n this.inputRef.removeEventListener('keydown', this.handleKeydown as EventListener)\n this.inputRef.removeEventListener('blur', this.handleInputBlur)\n }\n this.inputRef = null\n }\n\n /**\n * Clears event listeners from the current suggestions reference and resets it.\n */\n protected clearSuggestionsListeners(): void {\n if (this.suggestionsRef) {\n this.suggestionsRef.removeEventListener('select', this.handleSuggestionSelect as EventListener)\n // If ui-listbox uses a slot for its items, listen to its slotchange\n this.suggestionsRef.removeEventListener('itemschange', this.handleSuggestionsSlotChange)\n if (this.suggestionsRef.matches(':popover-open')) {\n this.suggestionsRef.hidePopover()\n }\n }\n this.suggestionsRef = null\n }\n\n /**\n * Sets up the slotted input element.\n * Assigns an ID if necessary, sets up CSS anchoring, and attaches event listeners.\n * @param input The HTMLElement to be used as the input.\n */\n protected setupInput(input: HTMLElement): void {\n this.clearInputListeners() // Clear any old listeners\n if (!input.id) {\n this.inputId = `autocomplete-input-${Math.random().toString(36).substring(2, 15)}`\n input.id = this.inputId\n } else {\n this.inputId = input.id\n }\n const anchorElement = this.querySelector('[slot=\"anchor\"]') as HTMLElement | null\n // Ensure CSS anchor positioning can work\n const anchor = anchorElement || input\n anchor.style.setProperty('anchor-name', `--${this.inputId}`)\n\n this.inputRef = input as HTMLInputElement // Assuming it behaves like an input\n this.inputRef.addEventListener('focus', this.handleInputFocus)\n this.inputRef.addEventListener('input', this.handleInput)\n this.inputRef.addEventListener('keydown', this.handleKeydown as EventListener)\n this.inputRef.addEventListener('blur', this.handleInputBlur)\n\n // Apply initial filtering if suggestions are already present\n if (this.suggestionsRef) {\n this.suggestionsRef.style.setProperty('position-anchor', `--${this.inputId}`)\n this.filterSuggestions((this.inputRef as HTMLInputElement).value || '')\n }\n }\n\n /**\n * Sets up the slotted suggestions element (assumed to be a `UiListbox`).\n * Configures popover behavior, CSS anchoring, and attaches event listeners.\n * @param suggestionsElement The `UiListbox` element to be used for suggestions.\n */\n protected setupSuggestions(suggestionsElement: UiListbox): void {\n this.clearSuggestionsListeners() // Clear any old listeners\n\n this.suggestionsRef = suggestionsElement\n this.suggestionsRef.popover = 'manual'\n this.suggestionsRef.tabIndex = -1 // Prevent direct focus\n\n if (this.inputId) {\n this.suggestionsRef.style.setProperty('position-anchor', `--${this.inputId}`)\n }\n\n this.suggestionsRef.addEventListener('select', this.handleSuggestionSelect as EventListener)\n // The `List` dispatches `itemschange` when the slot changes, so we can listen to it.\n this.suggestionsRef.addEventListener('itemschange', this.handleSuggestionsSlotChange)\n\n // Initial filter\n this.filterSuggestions(this.inputRef ? (this.inputRef as HTMLInputElement).value : '')\n }\n\n /**\n * Handles the focus event on the input element.\n * Opens the suggestions popover if there are items to display.\n */\n @bound\n protected handleInputFocus(): void {\n const items = this.suggestionsRef?.items\n if (!items || items.length === 0) {\n // If no suggestions, do not open\n return\n }\n const active = items.find((item) => !item.hidden)\n if (active) {\n this.openSuggestions()\n this.filterSuggestions(this.inputRef ? (this.inputRef as HTMLInputElement).value : '')\n }\n }\n\n /**\n * Handles the input event on the input element.\n * Filters suggestions based on the input query and opens/closes the popover accordingly.\n * @param event The input event.\n */\n @bound\n protected handleInput(event: Event): void {\n this.openSuggestions()\n const query = (event.target as HTMLInputElement).value\n this.filterSuggestions(query)\n }\n\n /**\n * Handles keydown events on the input element for navigating and selecting suggestions.\n * - ArrowDown/ArrowUp: Navigates the suggestion list.\n * - Enter: Selects the highlighted suggestion.\n * - Escape: Closes the suggestions popover.\n * @param event The keyboard event.\n */\n @bound\n protected handleKeydown(event: KeyboardEvent): void {\n if (!this.suggestionsRef) return\n\n const { key } = event\n const isSuggestionsOpen = this.suggestionsRef.matches(':popover-open')\n\n if (['ArrowDown', 'ArrowUp'].includes(key)) {\n event.preventDefault()\n if (!isSuggestionsOpen) {\n this.openSuggestions()\n // Give popover a moment to open before trying to highlight\n requestAnimationFrame(() => this.navigateList(key))\n } else {\n this.navigateList(key)\n }\n } else if (key === 'Enter') {\n if (isSuggestionsOpen && this.suggestionsRef.highlightListItem) {\n event.preventDefault()\n this.suggestionsRef.notifySelect(this.suggestionsRef.highlightListItem)\n }\n } else if (key === 'Escape') {\n if (isSuggestionsOpen) {\n event.preventDefault()\n this.closeSuggestions()\n }\n }\n }\n\n /**\n * Navigates the suggestion list based on the pressed key.\n * @param key The key that was pressed (ArrowDown or ArrowUp).\n */\n protected navigateList(key: string): void {\n if (!this.suggestionsRef) return\n switch (key) {\n case 'ArrowDown':\n this.suggestionsRef.highlightNext()\n break\n case 'ArrowUp':\n this.suggestionsRef.highlightPrevious()\n break\n // Don't handle Home or End keys here, as they break the usability of the input.\n }\n }\n\n /**\n * Handles the blur event on the input element.\n * Closes the suggestions popover if focus moves outside the autocomplete component.\n */\n @bound\n protected handleInputBlur(): void {\n // We use the manual popover mode, so we need to close suggestions\n // when the input loses focus, but only the current active element is not part of the suggestions.\n requestAnimationFrame(() => {\n if (\n !this.inputRef?.contains(document.activeElement) &&\n (!this.suggestionsRef || !this.suggestionsRef.contains(document.activeElement))\n ) {\n this.closeSuggestions()\n }\n })\n }\n\n /**\n * Handles the `select` event dispatched by the `ui-listbox` when a suggestion is chosen.\n * Dispatches an `autocomplete` event and closes the popover.\n * @param event The custom event from `ui-listbox`.\n */\n @bound\n protected handleSuggestionSelect(event: CustomEvent): void {\n event.stopPropagation()\n const selectedItem = event.detail.item as UiListItem\n this.dispatchEvent(\n new CustomEvent('autocomplete', {\n detail: { item: selectedItem },\n bubbles: false,\n composed: false,\n })\n )\n this.closeSuggestions()\n }\n\n /**\n * Handles the `itemschange` event dispatched by the `ui-listbox` when its slotted items change.\n * Re-filters the suggestions.\n */\n @bound\n protected handleSuggestionsSlotChange(): void {\n const value = this.inputRef ? (this.inputRef as HTMLInputElement).value : ''\n if (!value) {\n return\n }\n this.openSuggestions()\n this.filterSuggestions(value)\n }\n\n /**\n * Opens the suggestions popover if it's not already open and there are visible items.\n */\n protected openSuggestions(): void {\n const popover = this.suggestionsRef\n if (!popover || popover.matches(':popover-open')) {\n return\n }\n // we need to open the popover first to make any measurements\n popover.showPopover()\n const anchor = (this.querySelector('[slot=\"anchor\"]') as HTMLElement | null) || this.inputRef\n if (!anchor) {\n return\n }\n this.positionArea = this.decidePositionArea(popover, anchor)\n }\n\n /**\n * Decides the position area for the popover based on available space.\n * It checks if there is enough space below or above the anchor element and decides accordingly.\n *\n * We need to do this because we set the popover height to `100%`, `-webkit-fill-available`, or `-moz-available`\n * and it makes the popover to always open at the bottom, even if there is no space. The `position-try-fallbacks`\n * will not work in this case, because from its perspective there is always enough space, even if that will cause\n * the popover to have a height of just a few pixels.\n *\n * @param popover The popover element to position.\n * @param anchor The anchor element relative to which the popover will be positioned.\n * @returns 'top' or 'bottom' based on available space.\n */\n protected decidePositionArea(popover: HTMLElement, anchor: HTMLElement): 'top' | 'bottom' {\n let newArea: 'top' | 'bottom' = 'bottom'\n // Get bounding rectangles\n const anchorRect = anchor.getBoundingClientRect()\n const viewportHeight = window.innerHeight\n\n const spaceBelow = viewportHeight - anchorRect.bottom\n const spaceAbove = anchorRect.top\n\n // Estimate a typical/minimum height the popover might need to be useful\n const popoverThresholdHeight = popover.scrollHeight || 150\n if (spaceBelow < popoverThresholdHeight && spaceAbove > spaceBelow && spaceAbove > popoverThresholdHeight) {\n // Not enough space below, but more (and sufficient) space above\n newArea = 'top'\n } else if (spaceBelow < popoverThresholdHeight && spaceAbove > spaceBelow) {\n // Not enough space below, and space above is more than space below (even if not \"sufficient\")\n newArea = 'top'\n } else {\n newArea = 'bottom' // Default to bottom if enough space or if top is worse\n }\n return newArea\n }\n\n /**\n * Closes the suggestions popover if it's open and clears any highlighted item.\n */\n protected closeSuggestions(): void {\n if (this.suggestionsRef && this.suggestionsRef.matches(':popover-open')) {\n this.suggestionsRef.hidePopover()\n }\n }\n\n /**\n * Filters the suggestions based on the provided query.\n * Hides items that do not match and manages the highlighted item state.\n * @param query The search query string.\n */\n protected filterSuggestions(query: string): void {\n if (!this.suggestionsRef) {\n return\n }\n\n const lowerCaseQuery = query.toLowerCase().trim()\n let firstVisibleItem: UiListItem | null = null\n\n // The `items` getter in `List.ts` (parent of UiListbox) correctly gets assigned elements.\n const items = this.suggestionsRef.items as UiListItem[]\n\n for (const item of items) {\n let matches = false\n if (lowerCaseQuery === '') {\n matches = true\n } else if (item.dataset.index) {\n const indexFields = item.dataset.index.split(' ').filter(Boolean)\n for (const field of indexFields) {\n const valueToSearch = item.dataset[field] || ''\n if (valueToSearch.toLowerCase().includes(lowerCaseQuery)) {\n matches = true\n break\n }\n }\n } else {\n const valueToSearch = item.dataset.value || item.textContent || ''\n matches = valueToSearch.toLowerCase().includes(lowerCaseQuery)\n }\n item.hidden = !matches\n if (matches && !firstVisibleItem) {\n firstVisibleItem = item\n }\n }\n\n // If the currently highlighted item is now hidden, try to highlight the first visible one or clear.\n if (this.suggestionsRef.highlightListItem?.hidden) {\n // the highlightListItem clears the highlighted item if it is not passed an argument.\n this.suggestionsRef?.highlightItem(firstVisibleItem)\n }\n if (!firstVisibleItem) {\n // Close if no items are visible\n this.closeSuggestions()\n }\n }\n\n protected override render(): TemplateResult {\n const { id, positionArea } = this\n return html`\n <style>\n #${id} {\n display: inline-block;\n\n [popover] {\n border: none;\n margin: 0;\n position-area: ${positionArea};\n position-try-fallbacks:\n flip-block,\n flip-inline,\n flip-block flip-inline;\n width: anchor-size(width);\n\n box-shadow: var(--md-sys-elevation-1);\n border-radius: var(--md-sys-shape-corner-medium);\n\n overflow: auto;\n /* We try 100% and then vendor options which are more accurate */\n height: 100%;\n height: -webkit-fill-available;\n height: -moz-available;\n max-height: max-content;\n }\n\n [popover]:not(:popover-open) {\n display: none;\n }\n }\n </style>\n `\n }\n}\n"]}
|
|
1
|
+
{"version":3,"file":"autocomplete.js","sourceRoot":"","sources":["../../../../../src/elements/autocomplete/internals/autocomplete.ts"],"names":[],"mappings":"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","sourcesContent":["import { html, LitElement, PropertyValues, TemplateResult } from 'lit'\nimport { property, state } from 'lit/decorators.js'\nimport type UiListbox from '../../../md/listbox/internals/Listbox.js'\nimport type UiListItem from '../../../md/list/internals/ListItem.js'\nimport { bound } from '../../../decorators/bound.js'\n\n/**\n * An accessible and performant autocomplete component that enhances a text input with a list of suggestions.\n *\n * The `autocomplete-input` component provides a flexible way to add autocomplete functionality\n * to any text input. It works by coordinating a slotted input element with a slotted `ui-listbox`\n * containing suggestions.\n *\n * Key Features:\n *\n * - **Popover Management**: Automatically shows and hides the suggestions popover based on input focus\n * and user interaction.\n * - **Keyboard Navigation**: Allows users to navigate suggestions using ArrowUp, ArrowDown keys directly\n * from the input. Enter selects a suggestion, and Escape closes the popover.\n * The suggestion list itself never gains focus.\n * - **Dynamic Filtering**: Filters the list of suggestions as the user types into the input. Items not matching\n * the query are hidden (not removed).\n * - By default, filtering checks `item.dataset.value` and then `item.textContent`.\n * - If a `ui-list-item` has a `data-index` attribute (e.g., `data-index=\"name email\"`), filtering will search\n * within the specified `data-*` attributes (e.g., `data-name`, `data-email`).\n * - **Mutation Awareness**: Reacts to changes in slotted suggestions, re-filtering them if necessary.\n * - **Event-Driven**: Notifies the application via an `autocomplete` event when a suggestion is selected.\n * The component itself does not modify the input's value, giving the application author full control.\n *\n * ### Accessibility\n *\n * The `autocomplete-input` component is designed with accessibility at its core:\n * - **Keyboard Navigation**: Full keyboard support for navigating suggestions (ArrowUp, ArrowDown),\n * selecting (Enter), and closing (Escape), all while focus remains on the input field.\n * - **ARIA Attributes**: While the `autocomplete-input` manages ARIA attributes related to the popover's\n * state, the slotted `ui-listbox` is responsible for its internal ARIA roles and states\n * (e.g., `role=\"listbox\"`, `aria-activedescendant`).\n * - **Labeling Suggestions**: It is **crucial** for accessibility that the slotted `ui-listbox`\n * has an `aria-label` attribute. This provides a descriptive name for the list of suggestions,\n * which is announced by screen readers.\n *\n * The component uses CSS anchor positioning to place the suggestions popover relative to the input.\n * Ensure your `ui-listbox` is styled appropriately for popover display (e.g., `popover=\"manual\"`, `position-anchor`).\n * The component will manage `showPopover()` and `hidePopover()` calls.\n *\n * @slot input - The input element that will be used for autocomplete. This element should be an `HTMLInputElement`\n * or behave like one (have a `value` property and dispatch `input`, `focus`, `blur`, and `keydown`\n * events).\n * @slot suggestions - The `ui-listbox` element containing `ui-list-item` elements as suggestions.\n * @slot anchor - An optional element that points to element that will be used as the anchor for the popover.\n * This is useful if you want to position the suggestions relative to a different element than the input.\n * If not provided, the input element will be used as the anchor.\n * @slot Any additional content that should be rendered inside the component.\n *\n * @fires autocomplete - Dispatched when a suggestion is selected by the user (e.g., via click or Enter key).\n * The `event.detail` object contains:\n * - `item`: The selected `UiListItem` instance.\n *\n * @example\n * ```html\n * <autocomplete-input @autocomplete=\"${this.handleAutocompleteSelection}\">\n * <input slot=\"input\" type=\"text\" placeholder=\"Search fruits...\" />\n * <ui-listbox slot=\"suggestions\">\n * <ui-list-item data-value=\"apple\">Apple</ui-list-item>\n * <ui-list-item data-value=\"banana\">Banana</ui-list-item>\n * <ui-list-item data-value=\"cherry\">Cherry</ui-list-item>\n * </ui-listbox>\n * <!-- With aria-label for accessibility -->\n * <ui-listbox slot=\"suggestions\" aria-label=\"Fruit suggestions\">\n * <ui-list-item data-value=\"apple\">Apple</ui-list-item>\n * <ui-list-item data-value=\"banana\">Banana</ui-list-item>\n * <ui-list-item data-value=\"cherry\">Cherry</ui-list-item>\n * </ui-listbox>\n * </autocomplete-input>\n *\n * <script>\n * // In your component/script\n * handleAutocompleteSelection(event) {\n * const selectedItem = event.detail.item;\n * const inputElement = this.shadowRoot.querySelector('input[slot=\"input\"]');\n * if (inputElement) {\n * inputElement.value = selectedItem.dataset.value || selectedItem.textContent;\n * }\n * console.log('Selected:', selectedItem.dataset.value);\n * }\n * </script>\n * ```\n *\n * @example Dynamic filtering with `data-index`\n * ```html\n * <autocomplete-input @autocomplete=\"${this.handleUserSelection}\">\n * <input slot=\"input\" type=\"text\" placeholder=\"Search users...\" />\n * <ui-listbox slot=\"suggestions\" aria-label=\"User suggestions\">\n * <ui-list-item data-id=\"1\" data-name=\"Alice Wonderland\" data-email=\"alice@example.com\" data-index=\"name email\">\n * Alice Wonderland\n * <span slot=\"supporting-text\">alice@example.com</span>\n * </ui-list-item>\n * <ui-list-item data-id=\"2\" data-name=\"Bob The Builder\" data-email=\"bob@example.com\" data-index=\"name email\">\n * Bob The Builder\n * <span slot=\"supporting-text\">bob@example.com</span>\n * </ui-list-item>\n * </ui-listbox>\n * </autocomplete-input>\n *\n * <script>\n * // In your component/script\n * handleUserSelection(event) {\n * const selectedItem = event.detail.item;\n * const inputElement = this.shadowRoot.querySelector('input[slot=\"input\"]');\n * if (inputElement) {\n * // You might want to display the name, but store the ID\n * inputElement.value = selectedItem.dataset.name;\n * }\n * console.log('Selected user ID:', selectedItem.dataset.id);\n * }\n * </script>\n * ```\n */\nexport default class Autocomplete extends LitElement {\n protected override createRenderRoot(): HTMLElement | DocumentFragment {\n return this\n }\n\n /**\n * The MutationObserver instance used to watch for changes in slotted children.\n */\n protected observer?: MutationObserver\n\n /**\n * The ID of the input element, generated if not provided.\n * This is used for CSS anchoring and to ensure unique IDs for accessibility.\n */\n @state() protected accessor inputId = ''\n\n /**\n * The position area for the suggestions popover.\n * This can be 'bottom' or 'top', depending on available space.\n * Default is 'bottom'.\n *\n * Note, this is set dynamically based on available space\n * and the position of the input element. This only sets the initial value.\n *\n * @attribute\n * @type {'bottom' | 'top'}\n * @default 'bottom'\n */\n @property() accessor positionArea: 'bottom' | 'top' = 'bottom'\n\n /**\n * The reference to the slotted input element.\n * This should be an `HTMLInputElement` or behave like one.\n */\n protected inputRef?: HTMLInputElement | HTMLElement | null\n /**\n * The reference to the slotted suggestions element, which should be a `ui-listbox`.\n * This is used to manage the suggestions popover and filtering.\n */\n protected suggestionsRef?: UiListbox | null\n\n /**\n * Checks if the suggestions popover is currently open.\n */\n get opened(): boolean {\n return this.suggestionsRef?.matches(':popover-open') || false\n }\n\n override connectedCallback(): void {\n super.connectedCallback()\n this.observer = new MutationObserver(this.handleMutations.bind(this))\n this.observer.observe(this, { childList: true })\n if (!this.id) {\n this.id = `autocomplete-${Math.random().toString(36).substring(2, 15)}`\n }\n this.classList.add(this.id)\n }\n\n override disconnectedCallback(): void {\n super.disconnectedCallback()\n this.observer?.disconnect()\n this.observer = undefined\n this.clearInputListeners()\n this.clearSuggestionsListeners()\n }\n\n protected override firstUpdated(cp: PropertyValues): void {\n super.firstUpdated(cp)\n this.firstSetup()\n }\n\n /**\n * Performs initial setup after the first update, ensuring that slotted input\n * and suggestions elements are configured.\n */\n async firstSetup(): Promise<void> {\n await this.updateComplete\n const input = this.querySelector('[slot=\"input\"]') as HTMLElement | null\n const suggestions = this.querySelector('[slot=\"suggestions\"]') as HTMLElement | null\n if (input) {\n this.setupInput(input)\n }\n if (suggestions) {\n this.setupSuggestions(suggestions as UiListbox)\n }\n }\n\n /**\n * Handles mutations observed on the component's slotted children.\n * This is used to set up or tear down input and suggestions elements when they are added or removed.\n * @param mutations An array of MutationRecord objects.\n */\n protected handleMutations(mutations: MutationRecord[]): void {\n for (const mutation of mutations) {\n if (mutation.type === 'childList') {\n for (const node of mutation.removedNodes) {\n if (node instanceof HTMLElement) {\n if (node.slot === 'input' && this.inputRef === node) {\n this.clearInputListeners()\n } else if (node.slot === 'suggestions' && this.suggestionsRef === node) {\n this.clearSuggestionsListeners()\n }\n }\n }\n for (const node of mutation.addedNodes) {\n if (node instanceof HTMLElement) {\n if (node.slot === 'input') {\n this.setupInput(node)\n } else if (node.slot === 'suggestions') {\n this.setupSuggestions(node as UiListbox)\n }\n }\n }\n }\n }\n }\n\n /**\n * Clears event listeners from the current input reference and resets it.\n */\n protected clearInputListeners(): void {\n if (this.inputRef) {\n this.inputRef.removeEventListener('focus', this.handleInputFocus)\n this.inputRef.removeEventListener('input', this.handleInput)\n this.inputRef.removeEventListener('keydown', this.handleKeydown as EventListener)\n this.inputRef.removeEventListener('blur', this.handleInputBlur)\n }\n this.inputRef = null\n }\n\n /**\n * Clears event listeners from the current suggestions reference and resets it.\n */\n protected clearSuggestionsListeners(): void {\n if (this.suggestionsRef) {\n this.suggestionsRef.removeEventListener('select', this.handleSuggestionSelect as EventListener)\n // If ui-listbox uses a slot for its items, listen to its slotchange\n this.suggestionsRef.removeEventListener('itemschange', this.handleSuggestionsSlotChange)\n if (this.suggestionsRef.matches(':popover-open')) {\n this.suggestionsRef.hidePopover()\n }\n }\n this.suggestionsRef = null\n }\n\n /**\n * Sets up the slotted input element.\n * Assigns an ID if necessary, sets up CSS anchoring, and attaches event listeners.\n * @param input The HTMLElement to be used as the input.\n */\n protected setupInput(input: HTMLElement): void {\n this.clearInputListeners() // Clear any old listeners\n if (!input.id) {\n this.inputId = `autocomplete-input-${Math.random().toString(36).substring(2, 15)}`\n input.id = this.inputId\n } else {\n this.inputId = input.id\n }\n const anchorElement = this.querySelector('[slot=\"anchor\"]') as HTMLElement | null\n // Ensure CSS anchor positioning can work\n const anchor = anchorElement || input\n anchor.style.setProperty('anchor-name', `--${this.inputId}`)\n\n this.inputRef = input as HTMLInputElement // Assuming it behaves like an input\n this.inputRef.addEventListener('focus', this.handleInputFocus)\n this.inputRef.addEventListener('input', this.handleInput)\n this.inputRef.addEventListener('keydown', this.handleKeydown as EventListener)\n this.inputRef.addEventListener('blur', this.handleInputBlur)\n }\n\n /**\n * Sets up the slotted suggestions element (assumed to be a `UiListbox`).\n * Configures popover behavior, CSS anchoring, and attaches event listeners.\n * @param suggestionsElement The `UiListbox` element to be used for suggestions.\n */\n protected setupSuggestions(suggestionsElement: UiListbox): void {\n this.clearSuggestionsListeners() // Clear any old listeners\n\n this.suggestionsRef = suggestionsElement\n this.suggestionsRef.popover = 'manual'\n this.suggestionsRef.tabIndex = -1 // Prevent direct focus\n\n this.suggestionsRef.addEventListener('select', this.handleSuggestionSelect as EventListener)\n // The `List` dispatches `itemschange` when the slot changes, so we can listen to it.\n this.suggestionsRef.addEventListener('itemschange', this.handleSuggestionsSlotChange)\n\n // Initial filter\n this.filterSuggestions(this.inputRef ? (this.inputRef as HTMLInputElement).value : '')\n }\n\n /**\n * Handles the focus event on the input element.\n * Opens the suggestions popover if there are items to display.\n */\n @bound\n protected handleInputFocus(): void {\n const items = this.suggestionsRef?.items\n if (!items || items.length === 0) {\n // If no suggestions, do not open\n return\n }\n const active = items.find((item) => !item.hidden)\n if (active) {\n this.openSuggestions()\n this.filterSuggestions(this.inputRef ? (this.inputRef as HTMLInputElement).value : '')\n }\n }\n\n /**\n * Handles the input event on the input element.\n * Filters suggestions based on the input query and opens/closes the popover accordingly.\n * @param event The input event.\n */\n @bound\n protected handleInput(event: Event): void {\n this.openSuggestions()\n const query = (event.target as HTMLInputElement).value\n this.filterSuggestions(query)\n }\n\n /**\n * Handles keydown events on the input element for navigating and selecting suggestions.\n * - ArrowDown/ArrowUp: Navigates the suggestion list.\n * - Enter: Selects the highlighted suggestion.\n * - Escape: Closes the suggestions popover.\n * @param event The keyboard event.\n */\n @bound\n protected handleKeydown(event: KeyboardEvent): void {\n if (!this.suggestionsRef) return\n\n const { key } = event\n const isSuggestionsOpen = this.suggestionsRef.matches(':popover-open')\n\n if (['ArrowDown', 'ArrowUp'].includes(key)) {\n event.preventDefault()\n if (!isSuggestionsOpen) {\n this.openSuggestions()\n // Give popover a moment to open before trying to highlight\n requestAnimationFrame(() => this.navigateList(key))\n } else {\n this.navigateList(key)\n }\n } else if (key === 'Enter') {\n if (isSuggestionsOpen && this.suggestionsRef.highlightListItem) {\n event.preventDefault()\n this.suggestionsRef.notifySelect(this.suggestionsRef.highlightListItem)\n }\n } else if (key === 'Escape') {\n if (isSuggestionsOpen) {\n event.preventDefault()\n this.closeSuggestions()\n }\n }\n }\n\n /**\n * Navigates the suggestion list based on the pressed key.\n * @param key The key that was pressed (ArrowDown or ArrowUp).\n */\n protected navigateList(key: string): void {\n if (!this.suggestionsRef) return\n switch (key) {\n case 'ArrowDown':\n this.suggestionsRef.highlightNext()\n break\n case 'ArrowUp':\n this.suggestionsRef.highlightPrevious()\n break\n // Don't handle Home or End keys here, as they break the usability of the input.\n }\n }\n\n /**\n * Handles the blur event on the input element.\n * Closes the suggestions popover if focus moves outside the autocomplete component.\n */\n @bound\n protected handleInputBlur(): void {\n // We use the manual popover mode, so we need to close suggestions\n // when the input loses focus, but only the current active element is not part of the suggestions.\n requestAnimationFrame(() => {\n if (\n !this.inputRef?.contains(document.activeElement) &&\n (!this.suggestionsRef || !this.suggestionsRef.contains(document.activeElement))\n ) {\n this.closeSuggestions()\n }\n })\n }\n\n /**\n * Handles the `select` event dispatched by the `ui-listbox` when a suggestion is chosen.\n * Dispatches an `autocomplete` event and closes the popover.\n * @param event The custom event from `ui-listbox`.\n */\n @bound\n protected handleSuggestionSelect(event: CustomEvent): void {\n event.stopPropagation()\n const selectedItem = event.detail.item as UiListItem\n this.dispatchEvent(\n new CustomEvent('autocomplete', {\n detail: { item: selectedItem },\n bubbles: false,\n composed: false,\n })\n )\n this.closeSuggestions()\n }\n\n /**\n * Handles the `itemschange` event dispatched by the `ui-listbox` when its slotted items change.\n * Re-filters the suggestions.\n */\n @bound\n protected handleSuggestionsSlotChange(): void {\n const value = this.inputRef ? (this.inputRef as HTMLInputElement).value : ''\n if (!value) {\n return\n }\n this.openSuggestions()\n this.filterSuggestions(value)\n }\n\n /**\n * Opens the suggestions popover if it's not already open and there are visible items.\n */\n protected openSuggestions(): void {\n const popover = this.suggestionsRef\n if (!popover || popover.matches(':popover-open')) {\n return\n }\n // we need to open the popover first to make any measurements\n popover.showPopover()\n const anchor = (this.querySelector('[slot=\"anchor\"]') as HTMLElement | null) || this.inputRef\n if (!anchor) {\n return\n }\n this.positionArea = this.decidePositionArea(popover, anchor)\n }\n\n /**\n * Decides the position area for the popover based on available space.\n * It checks if there is enough space below or above the anchor element and decides accordingly.\n *\n * We need to do this because we set the popover height to `100%`, `-webkit-fill-available`, or `-moz-available`\n * and it makes the popover to always open at the bottom, even if there is no space. The `position-try-fallbacks`\n * will not work in this case, because from its perspective there is always enough space, even if that will cause\n * the popover to have a height of just a few pixels.\n *\n * @param popover The popover element to position.\n * @param anchor The anchor element relative to which the popover will be positioned.\n * @returns 'top' or 'bottom' based on available space.\n */\n protected decidePositionArea(popover: HTMLElement, anchor: HTMLElement): 'top' | 'bottom' {\n let newArea: 'top' | 'bottom' = 'bottom'\n // Get bounding rectangles\n const anchorRect = anchor.getBoundingClientRect()\n const viewportHeight = window.innerHeight\n\n const spaceBelow = viewportHeight - anchorRect.bottom\n const spaceAbove = anchorRect.top\n\n // Estimate a typical/minimum height the popover might need to be useful\n const popoverThresholdHeight = popover.scrollHeight || 150\n if (spaceBelow < popoverThresholdHeight && spaceAbove > spaceBelow && spaceAbove > popoverThresholdHeight) {\n // Not enough space below, but more (and sufficient) space above\n newArea = 'top'\n } else if (spaceBelow < popoverThresholdHeight && spaceAbove > spaceBelow) {\n // Not enough space below, and space above is more than space below (even if not \"sufficient\")\n newArea = 'top'\n } else {\n newArea = 'bottom' // Default to bottom if enough space or if top is worse\n }\n return newArea\n }\n\n /**\n * Closes the suggestions popover if it's open and clears any highlighted item.\n */\n protected closeSuggestions(): void {\n if (this.suggestionsRef && this.suggestionsRef.matches(':popover-open')) {\n this.suggestionsRef.hidePopover()\n }\n }\n\n /**\n * Filters the suggestions based on the provided query.\n * Hides items that do not match and manages the highlighted item state.\n * @param query The search query string.\n */\n protected filterSuggestions(query: string): void {\n if (!this.suggestionsRef) {\n return\n }\n\n const lowerCaseQuery = query.toLowerCase().trim()\n let firstVisibleItem: UiListItem | null = null\n\n // The `items` getter in `List.ts` (parent of UiListbox) correctly gets assigned elements.\n const items = this.suggestionsRef.items as UiListItem[]\n\n for (const item of items) {\n let matches = false\n if (lowerCaseQuery === '') {\n matches = true\n } else if (item.dataset.index) {\n const indexFields = item.dataset.index.split(' ').filter(Boolean)\n for (const field of indexFields) {\n const valueToSearch = item.dataset[field] || ''\n if (valueToSearch.toLowerCase().includes(lowerCaseQuery)) {\n matches = true\n break\n }\n }\n } else {\n const valueToSearch = item.dataset.value || item.textContent || ''\n matches = valueToSearch.toLowerCase().includes(lowerCaseQuery)\n }\n item.hidden = !matches\n if (matches && !firstVisibleItem) {\n firstVisibleItem = item\n }\n }\n\n // If the currently highlighted item is now hidden, try to highlight the first visible one or clear.\n if (this.suggestionsRef.highlightListItem?.hidden) {\n // the highlightListItem clears the highlighted item if it is not passed an argument.\n this.suggestionsRef?.highlightItem(firstVisibleItem)\n }\n if (!firstVisibleItem) {\n // Close if no items are visible\n this.closeSuggestions()\n }\n }\n\n protected override render(): TemplateResult {\n const { id, positionArea, inputId } = this\n /*\n position-try-fallbacks:\n flip-block,\n flip-inline,\n flip-block flip-inline;\n */\n return html`\n <style>\n .${id} {\n display: inline-block;\n\n [popover] {\n border: none;\n margin: 0;\n\n box-shadow: var(--md-sys-elevation-1);\n border-radius: var(--md-sys-shape-corner-medium);\n\n position-area: ${positionArea};\n position-anchor: --${inputId};\n\n overflow: auto;\n /* We try 100% and then vendor options which are more accurate */\n height: 100%;\n height: -webkit-fill-available;\n height: -moz-available;\n max-height: max-content;\n width: anchor-size(width);\n }\n\n [popover]:not(:popover-open) {\n display: none;\n }\n }\n </style>\n `\n }\n}\n"]}
|
|
@@ -129,12 +129,13 @@ export default class MarkedHighlight extends LitElement {
|
|
|
129
129
|
* @returns A reference to the output element.
|
|
130
130
|
*/
|
|
131
131
|
get outputElement(): HTMLElement | null;
|
|
132
|
-
protected
|
|
132
|
+
protected willUpdate(cp: PropertyValues<this>): void;
|
|
133
133
|
protected markdownElement?: HTMLScriptElement | null;
|
|
134
134
|
protected attachedValue: boolean;
|
|
135
135
|
firstUpdated(): void;
|
|
136
136
|
connectedCallback(): void;
|
|
137
137
|
disconnectedCallback(): void;
|
|
138
|
+
protected processScript(): Promise<void>;
|
|
138
139
|
/**
|
|
139
140
|
* Renders `markdown` into this element's DOM.
|
|
140
141
|
*
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"MarkedHighlight.d.ts","sourceRoot":"","sources":["../../../../src/elements/highlight/MarkedHighlight.ts"],"names":[],"mappings":"AAAA,OAAO,EAAQ,UAAU,EAAE,cAAc,EAAE,cAAc,EAAE,MAAM,KAAK,CAAA;AAMtE;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA2EG;AACH,MAAM,CAAC,OAAO,OAAO,eAAgB,SAAQ,UAAU;IACrD;;;OAGG;IACyB,QAAQ,CAAC,QAAQ,EAAE,MAAM,GAAG,SAAS,CAAA;IAEjE;;;;OAIG;IACyC,QAAQ,CAAC,MAAM,EAAE,OAAO,GAAG,SAAS,CAAA;IAEhF;;;;OAIG;IACyC,QAAQ,CAAC,QAAQ,EAAE,OAAO,GAAG,SAAS,CAAA;IAElF;;;;;;OAMG;IAEyB,QAAQ,CAAC,QAAQ,EAAE,QAAQ,GAAG,SAAS,CAAA;IAEnE;;;OAGG;IACyC,QAAQ,CAAC,QAAQ,EAAE,OAAO,GAAG,SAAS,CAAA;IAElF;;;;;;;;OAQG;IAEyB,QAAQ,CAAC,SAAS,EAAE,QAAQ,GAAG,SAAS,CAAA;IAEpE;;;;;;;OAOG;IACyC,QAAQ,CAAC,yBAAyB,EAAE,OAAO,GAAG,SAAS,CAAA;IAEnG;;OAEG;IACH,IAAI,aAAa,IAAI,WAAW,GAAG,IAAI,CAUtC;cAEkB,
|
|
1
|
+
{"version":3,"file":"MarkedHighlight.d.ts","sourceRoot":"","sources":["../../../../src/elements/highlight/MarkedHighlight.ts"],"names":[],"mappings":"AAAA,OAAO,EAAQ,UAAU,EAAE,cAAc,EAAE,cAAc,EAAE,MAAM,KAAK,CAAA;AAMtE;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA2EG;AACH,MAAM,CAAC,OAAO,OAAO,eAAgB,SAAQ,UAAU;IACrD;;;OAGG;IACyB,QAAQ,CAAC,QAAQ,EAAE,MAAM,GAAG,SAAS,CAAA;IAEjE;;;;OAIG;IACyC,QAAQ,CAAC,MAAM,EAAE,OAAO,GAAG,SAAS,CAAA;IAEhF;;;;OAIG;IACyC,QAAQ,CAAC,QAAQ,EAAE,OAAO,GAAG,SAAS,CAAA;IAElF;;;;;;OAMG;IAEyB,QAAQ,CAAC,QAAQ,EAAE,QAAQ,GAAG,SAAS,CAAA;IAEnE;;;OAGG;IACyC,QAAQ,CAAC,QAAQ,EAAE,OAAO,GAAG,SAAS,CAAA;IAElF;;;;;;;;OAQG;IAEyB,QAAQ,CAAC,SAAS,EAAE,QAAQ,GAAG,SAAS,CAAA;IAEpE;;;;;;;OAOG;IACyC,QAAQ,CAAC,yBAAyB,EAAE,OAAO,GAAG,SAAS,CAAA;IAEnG;;OAEG;IACH,IAAI,aAAa,IAAI,WAAW,GAAG,IAAI,CAUtC;cAEkB,UAAU,CAAC,EAAE,EAAE,cAAc,CAAC,IAAI,CAAC,GAAG,IAAI;IAc7D,SAAS,CAAC,eAAe,CAAC,EAAE,iBAAiB,GAAG,IAAI,CAAA;IAEpD,SAAS,CAAC,aAAa,UAAQ;IAEtB,YAAY,IAAI,IAAI;IAOpB,iBAAiB,IAAI,IAAI;IAOzB,oBAAoB,IAAI,IAAI;cAKrB,aAAa,IAAI,OAAO,CAAC,IAAI,CAAC;IAsB9C;;;;;;;;;OASG;IACH,cAAc,IAAI,IAAI;IA0CtB;;OAEG;IACH,QAAQ,CAAC,IAAI,CAAC,EAAE,MAAM,GAAG,MAAM;IA6B/B;;OAEG;cACa,eAAe,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IAkB3D;;OAEG;IACH,SAAS,CAAC,WAAW,CAAC,CAAC,EAAE,KAAK,GAAG,IAAI;IAarC,SAAS,CAAC,sBAAsB,CAAC,QAAQ,EAAE,cAAc,EAAE,GAAG,IAAI;IAUzD,MAAM,IAAI,cAAc;CAGlC"}
|
|
@@ -122,8 +122,8 @@ let MarkedHighlight = (() => {
|
|
|
122
122
|
const child = nodes.find((node) => node.nodeType === 1 && node.getAttribute('slot') === 'markdown-html');
|
|
123
123
|
return child || this.shadowRoot?.querySelector('#content');
|
|
124
124
|
}
|
|
125
|
-
|
|
126
|
-
super.
|
|
125
|
+
willUpdate(cp) {
|
|
126
|
+
super.willUpdate(cp);
|
|
127
127
|
if (cp.has('markdown') ||
|
|
128
128
|
cp.has('sanitizer') ||
|
|
129
129
|
cp.has('sanitize') ||
|
|
@@ -140,6 +140,18 @@ let MarkedHighlight = (() => {
|
|
|
140
140
|
this.renderMarkdown();
|
|
141
141
|
return;
|
|
142
142
|
}
|
|
143
|
+
}
|
|
144
|
+
connectedCallback() {
|
|
145
|
+
super.connectedCallback();
|
|
146
|
+
this.attachedValue = true;
|
|
147
|
+
this.processScript();
|
|
148
|
+
this.renderMarkdown();
|
|
149
|
+
}
|
|
150
|
+
disconnectedCallback() {
|
|
151
|
+
super.disconnectedCallback();
|
|
152
|
+
this.attachedValue = false;
|
|
153
|
+
}
|
|
154
|
+
async processScript() {
|
|
143
155
|
// Use the Markdown from the first `<script>` descendant whose MIME type
|
|
144
156
|
// starts with "text/markdown". Script elements beyond the first are
|
|
145
157
|
// ignored.
|
|
@@ -158,15 +170,6 @@ let MarkedHighlight = (() => {
|
|
|
158
170
|
const observer = new MutationObserver(this.scriptAttributeHandler.bind(this));
|
|
159
171
|
observer.observe(script, { attributes: true });
|
|
160
172
|
}
|
|
161
|
-
connectedCallback() {
|
|
162
|
-
super.connectedCallback();
|
|
163
|
-
this.attachedValue = true;
|
|
164
|
-
this.renderMarkdown();
|
|
165
|
-
}
|
|
166
|
-
disconnectedCallback() {
|
|
167
|
-
super.disconnectedCallback();
|
|
168
|
-
this.attachedValue = false;
|
|
169
|
-
}
|
|
170
173
|
/**
|
|
171
174
|
* Renders `markdown` into this element's DOM.
|
|
172
175
|
*
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"MarkedHighlight.js","sourceRoot":"","sources":["../../../../src/elements/highlight/MarkedHighlight.ts"],"names":[],"mappings":"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","sourcesContent":["import { html, LitElement, TemplateResult, PropertyValues } from 'lit'\nimport { property } from 'lit/decorators.js'\nimport DOMPurify from 'dompurify'\nimport { marked, MarkedOptions } from 'marked'\n// import { PrismHighlighter } from './PrismHighlighter.js';\n\n/**\nElement wrapper for the [marked](https://github.com/chjj/marked) library.\n\n`<marked-highlight>` accepts Markdown source and renders it to a child\nelement with the class `markdown-html`. This child element can be styled\nas you would a normal DOM element. If you do not provide a child element\nwith the `markdown-html` class, the Markdown source will still be rendered,\nbut to a shadow DOM child that cannot be styled.\n\n### Markdown Content\n\nThe Markdown source can be specified several ways:\n\n#### Use the `markdown` attribute to bind markdown\n\n```html\n<marked-highlight markdown=\"`Markdown` is _awesome_!\">\n <div slot=\"markdown-html\"></div>\n</marked-highlight>\n```\n#### Use `<script type=\"text/markdown\">` element child to inline markdown\n\n```html\n<marked-highlight>\n <div slot=\"markdown-html\"></div>\n <script type=\"text/markdown\">\n Check out my markdown!\n We can even embed elements without fear of the HTML parser mucking up their\n textual representation:\n </script>\n</marked-highlight>\n```\n#### Use `<script type=\"text/markdown\" src=\"URL\">` element child to specify remote markdown\n\n```html\n<marked-highlight>\n <div slot=\"markdown-html\"></div>\n <script type=\"text/markdown\" src=\"../guidelines.md\"></script>\n</marked-highlight>\n```\n\nNote that the `<script type=\"text/markdown\">` approach is *static*. Changes to\nthe script content will *not* update the rendered markdown!\n\nThough, you can data bind to the `src` attribute to change the markdown.\n\n```html\n<marked-highlight>\n <div slot=\"markdown-html\"></div>\n <script type=\"text/markdown\" src$=\"[[source]]\"></script>\n</marked-highlight>\n<script>\n ...\n this.source = '../guidelines.md';\n</script>\n```\n\n### Styling\n\nIf you are using a child with the `markdown-html` class, you can style it\nas you would a regular DOM element:\n\n```css\n[slot=\"markdown-html\"] p {\n color: red;\n}\n[slot=\"markdown-html\"] td:first-child {\n padding-left: 24px;\n}\n```\n\n@fires markedrendercomplete - Event dispatched when the element renders the output.\n@fires markedloaded - Event dispatched when the element loads the script from the URL.\n@fires markedloaderror - An event dispatched when an error ocurred when downloading\n the script content. The detail has the original error.\n */\nexport default class MarkedHighlight extends LitElement {\n /**\n * The markdown source to be rendered by this element.\n * @attribute\n */\n @property({ type: String }) accessor markdown: string | undefined\n\n /**\n * Enable GFM line breaks (regular newlines instead of two spaces for\n * breaks)\n * @attribute\n */\n @property({ type: Boolean, reflect: true }) accessor breaks: boolean | undefined\n\n /**\n * Conform to obscure parts of markdown.pl as much as possible. Don't fix\n * any of the original markdown bugs or poor behavior.\n * @attribute\n */\n @property({ type: Boolean, reflect: true }) accessor pedantic: boolean | undefined\n\n /**\n * Function used to customize a renderer based on the [API specified in the\n * Marked\n * library](https://github.com/chjj/marked#overriding-renderer-methods).\n * It takes one argument: a marked renderer object, which is mutated by the\n * function.\n */\n // eslint-disable-next-line @typescript-eslint/no-unsafe-function-type\n @property({ type: Object }) accessor renderer: Function | undefined\n\n /**\n * Sanitize the output. Ignore any HTML that has been input.\n * @attribute\n */\n @property({ type: Boolean, reflect: true }) accessor sanitize: boolean | undefined\n\n /**\n * Function used to customize a sanitize behavior.\n * It takes one argument: element String without text Contents.\n *\n * e.g. `<div>` `<a href=\"/\">` `</p>'.\n * Note: To enable this function, must set `sanitize` to true.\n * WARNING: If you are using this option to un-trusted text, you must to\n * prevent XSS Attacks.\n */\n // eslint-disable-next-line @typescript-eslint/no-unsafe-function-type\n @property({ type: Object }) accessor sanitizer: Function | undefined\n\n /**\n * If true, disables the default sanitization of any markdown received by\n * a request and allows fetched un-sanitized markdown\n *\n * e.g. fetching markdown via `src` that has HTML.\n * Note: this value overrides `sanitize` if a request is made.\n * @attribute\n */\n @property({ type: Boolean, reflect: true }) accessor disableRemoteSanitization: boolean | undefined\n\n /**\n * @returns A reference to the output element.\n */\n get outputElement(): HTMLElement | null {\n const slot = this.shadowRoot?.querySelector('slot[name=\"markdown-html\"]') as HTMLSlotElement | null\n if (!slot) {\n return null\n }\n const nodes = slot.assignedNodes()\n const child = nodes.find(\n (node) => node.nodeType === 1 && (node as HTMLElement).getAttribute('slot') === 'markdown-html'\n ) as HTMLElement | undefined\n return child || (this.shadowRoot?.querySelector('#content') as HTMLElement | null)\n }\n\n protected override updated(cp: PropertyValues<this>): void {\n super.updated(cp)\n if (\n cp.has('markdown') ||\n cp.has('sanitizer') ||\n cp.has('sanitize') ||\n cp.has('renderer') ||\n cp.has('pedantic') ||\n cp.has('breaks')\n ) {\n this.renderMarkdown()\n }\n }\n\n protected markdownElement?: HTMLScriptElement | null\n\n protected attachedValue = false\n\n override firstUpdated(): void {\n if (this.markdown) {\n this.renderMarkdown()\n return\n }\n\n // Use the Markdown from the first `<script>` descendant whose MIME type\n // starts with \"text/markdown\". Script elements beyond the first are\n // ignored.\n const script = this.querySelector('[type=\"text/markdown\"]') as HTMLScriptElement | null\n if (!script) {\n return\n }\n this.markdownElement = script\n\n if (script.src) {\n this.requestMarkdown(script.src)\n }\n const content = script.textContent\n if (content && content.trim() !== '') {\n this.markdown = this.unindent(content)\n }\n\n const observer = new MutationObserver(this.scriptAttributeHandler.bind(this))\n observer.observe(script, { attributes: true })\n }\n\n override connectedCallback(): void {\n super.connectedCallback()\n this.attachedValue = true\n this.renderMarkdown()\n }\n\n override disconnectedCallback(): void {\n super.disconnectedCallback()\n this.attachedValue = false\n }\n\n /**\n * Renders `markdown` into this element's DOM.\n *\n * This is automatically called whenever the `markdown` property is changed.\n *\n * The only case where you should be calling this is if you are providing\n * markdown via `<script type=\"text/markdown\">` after this element has been\n * constructed (or updating that markdown).\n * @event markedrendercomplete\n */\n renderMarkdown(): void {\n if (!this.attachedValue) {\n return\n }\n const node = this.outputElement\n if (!node) {\n return\n }\n\n if (!this.markdown) {\n node.innerHTML = ''\n return\n }\n const renderer = new marked.Renderer()\n if (this.renderer) {\n this.renderer(renderer)\n }\n const data = this.markdown\n const opts: MarkedOptions = {\n renderer,\n breaks: this.breaks,\n pedantic: this.pedantic,\n gfm: true,\n }\n let out = marked(data, opts) as string\n if (this.sanitize) {\n if (this.sanitizer) {\n out = this.sanitizer(out)\n } else {\n const result = DOMPurify.sanitize(out)\n if (typeof result === 'string') {\n out = result\n } else {\n // @ts-expect-error Sometimes the result is an object!\n out = result.toString()\n }\n }\n }\n node.innerHTML = out\n this.dispatchEvent(new Event('markedrendercomplete'))\n }\n\n /**\n * Un-indents the markdown source that will be rendered.\n */\n unindent(text?: string): string {\n if (!text) {\n return ''\n }\n const lines = text.replace(/\\t/g, ' ').split('\\n')\n const indent = lines.reduce((prev: number | null, line: string): number | null => {\n if (/^\\s*$/.test(line)) {\n return prev // Completely ignore blank lines.\n }\n const match = line.match(/^(\\s*)/)\n if (!match) {\n return prev\n }\n\n const lineIndent = match[0].length\n if (prev === null) {\n return lineIndent\n }\n\n return lineIndent < prev ? lineIndent : prev\n }, null)\n\n if (indent === null) {\n return text\n }\n\n return lines.map((l) => l.substring(indent)).join('\\n')\n }\n\n /**\n * Fired when the XHR finishes loading\n */\n protected async requestMarkdown(url: string): Promise<void> {\n try {\n const response = await fetch(url, {\n headers: { accept: 'text/markdown' },\n })\n const { status } = response\n if (status === 0 || (status >= 200 && status < 300)) {\n this.sanitize = !this.disableRemoteSanitization\n this.markdown = await response.text()\n this.dispatchEvent(new Event('markedloaded'))\n } else {\n throw new Error('Unable to download the data')\n }\n } catch (e) {\n this.handleError(e as Error)\n }\n }\n\n /**\n * Fired when an error is received while fetching remote markdown content.\n */\n protected handleError(e: Error): void {\n const evt = new CustomEvent('markedloaderror', {\n composed: true,\n bubbles: true,\n cancelable: true,\n detail: e,\n })\n this.dispatchEvent(evt)\n if (!evt.defaultPrevented) {\n this.markdown = 'Failed loading markdown source'\n }\n }\n\n protected scriptAttributeHandler(mutation: MutationRecord[]): void {\n if (mutation[0].attributeName !== 'src') {\n return\n }\n const elm = this.markdownElement\n if (elm) {\n this.requestMarkdown(elm.src)\n }\n }\n\n override render(): TemplateResult {\n return html`<slot name=\"markdown-html\"><div id=\"content\"></div></slot>`\n }\n}\n"]}
|
|
1
|
+
{"version":3,"file":"MarkedHighlight.js","sourceRoot":"","sources":["../../../../src/elements/highlight/MarkedHighlight.ts"],"names":[],"mappings":"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","sourcesContent":["import { html, LitElement, TemplateResult, PropertyValues } from 'lit'\nimport { property } from 'lit/decorators.js'\nimport DOMPurify from 'dompurify'\nimport { marked, MarkedOptions } from 'marked'\n// import { PrismHighlighter } from './PrismHighlighter.js';\n\n/**\nElement wrapper for the [marked](https://github.com/chjj/marked) library.\n\n`<marked-highlight>` accepts Markdown source and renders it to a child\nelement with the class `markdown-html`. This child element can be styled\nas you would a normal DOM element. If you do not provide a child element\nwith the `markdown-html` class, the Markdown source will still be rendered,\nbut to a shadow DOM child that cannot be styled.\n\n### Markdown Content\n\nThe Markdown source can be specified several ways:\n\n#### Use the `markdown` attribute to bind markdown\n\n```html\n<marked-highlight markdown=\"`Markdown` is _awesome_!\">\n <div slot=\"markdown-html\"></div>\n</marked-highlight>\n```\n#### Use `<script type=\"text/markdown\">` element child to inline markdown\n\n```html\n<marked-highlight>\n <div slot=\"markdown-html\"></div>\n <script type=\"text/markdown\">\n Check out my markdown!\n We can even embed elements without fear of the HTML parser mucking up their\n textual representation:\n </script>\n</marked-highlight>\n```\n#### Use `<script type=\"text/markdown\" src=\"URL\">` element child to specify remote markdown\n\n```html\n<marked-highlight>\n <div slot=\"markdown-html\"></div>\n <script type=\"text/markdown\" src=\"../guidelines.md\"></script>\n</marked-highlight>\n```\n\nNote that the `<script type=\"text/markdown\">` approach is *static*. Changes to\nthe script content will *not* update the rendered markdown!\n\nThough, you can data bind to the `src` attribute to change the markdown.\n\n```html\n<marked-highlight>\n <div slot=\"markdown-html\"></div>\n <script type=\"text/markdown\" src$=\"[[source]]\"></script>\n</marked-highlight>\n<script>\n ...\n this.source = '../guidelines.md';\n</script>\n```\n\n### Styling\n\nIf you are using a child with the `markdown-html` class, you can style it\nas you would a regular DOM element:\n\n```css\n[slot=\"markdown-html\"] p {\n color: red;\n}\n[slot=\"markdown-html\"] td:first-child {\n padding-left: 24px;\n}\n```\n\n@fires markedrendercomplete - Event dispatched when the element renders the output.\n@fires markedloaded - Event dispatched when the element loads the script from the URL.\n@fires markedloaderror - An event dispatched when an error ocurred when downloading\n the script content. The detail has the original error.\n */\nexport default class MarkedHighlight extends LitElement {\n /**\n * The markdown source to be rendered by this element.\n * @attribute\n */\n @property({ type: String }) accessor markdown: string | undefined\n\n /**\n * Enable GFM line breaks (regular newlines instead of two spaces for\n * breaks)\n * @attribute\n */\n @property({ type: Boolean, reflect: true }) accessor breaks: boolean | undefined\n\n /**\n * Conform to obscure parts of markdown.pl as much as possible. Don't fix\n * any of the original markdown bugs or poor behavior.\n * @attribute\n */\n @property({ type: Boolean, reflect: true }) accessor pedantic: boolean | undefined\n\n /**\n * Function used to customize a renderer based on the [API specified in the\n * Marked\n * library](https://github.com/chjj/marked#overriding-renderer-methods).\n * It takes one argument: a marked renderer object, which is mutated by the\n * function.\n */\n // eslint-disable-next-line @typescript-eslint/no-unsafe-function-type\n @property({ type: Object }) accessor renderer: Function | undefined\n\n /**\n * Sanitize the output. Ignore any HTML that has been input.\n * @attribute\n */\n @property({ type: Boolean, reflect: true }) accessor sanitize: boolean | undefined\n\n /**\n * Function used to customize a sanitize behavior.\n * It takes one argument: element String without text Contents.\n *\n * e.g. `<div>` `<a href=\"/\">` `</p>'.\n * Note: To enable this function, must set `sanitize` to true.\n * WARNING: If you are using this option to un-trusted text, you must to\n * prevent XSS Attacks.\n */\n // eslint-disable-next-line @typescript-eslint/no-unsafe-function-type\n @property({ type: Object }) accessor sanitizer: Function | undefined\n\n /**\n * If true, disables the default sanitization of any markdown received by\n * a request and allows fetched un-sanitized markdown\n *\n * e.g. fetching markdown via `src` that has HTML.\n * Note: this value overrides `sanitize` if a request is made.\n * @attribute\n */\n @property({ type: Boolean, reflect: true }) accessor disableRemoteSanitization: boolean | undefined\n\n /**\n * @returns A reference to the output element.\n */\n get outputElement(): HTMLElement | null {\n const slot = this.shadowRoot?.querySelector('slot[name=\"markdown-html\"]') as HTMLSlotElement | null\n if (!slot) {\n return null\n }\n const nodes = slot.assignedNodes()\n const child = nodes.find(\n (node) => node.nodeType === 1 && (node as HTMLElement).getAttribute('slot') === 'markdown-html'\n ) as HTMLElement | undefined\n return child || (this.shadowRoot?.querySelector('#content') as HTMLElement | null)\n }\n\n protected override willUpdate(cp: PropertyValues<this>): void {\n super.willUpdate(cp)\n if (\n cp.has('markdown') ||\n cp.has('sanitizer') ||\n cp.has('sanitize') ||\n cp.has('renderer') ||\n cp.has('pedantic') ||\n cp.has('breaks')\n ) {\n this.renderMarkdown()\n }\n }\n\n protected markdownElement?: HTMLScriptElement | null\n\n protected attachedValue = false\n\n override firstUpdated(): void {\n if (this.markdown) {\n this.renderMarkdown()\n return\n }\n }\n\n override connectedCallback(): void {\n super.connectedCallback()\n this.attachedValue = true\n this.processScript()\n this.renderMarkdown()\n }\n\n override disconnectedCallback(): void {\n super.disconnectedCallback()\n this.attachedValue = false\n }\n\n protected async processScript(): Promise<void> {\n // Use the Markdown from the first `<script>` descendant whose MIME type\n // starts with \"text/markdown\". Script elements beyond the first are\n // ignored.\n const script = this.querySelector('[type=\"text/markdown\"]') as HTMLScriptElement | null\n if (!script) {\n return\n }\n this.markdownElement = script\n\n if (script.src) {\n this.requestMarkdown(script.src)\n }\n const content = script.textContent\n if (content && content.trim() !== '') {\n this.markdown = this.unindent(content)\n }\n\n const observer = new MutationObserver(this.scriptAttributeHandler.bind(this))\n observer.observe(script, { attributes: true })\n }\n\n /**\n * Renders `markdown` into this element's DOM.\n *\n * This is automatically called whenever the `markdown` property is changed.\n *\n * The only case where you should be calling this is if you are providing\n * markdown via `<script type=\"text/markdown\">` after this element has been\n * constructed (or updating that markdown).\n * @event markedrendercomplete\n */\n renderMarkdown(): void {\n if (!this.attachedValue) {\n return\n }\n const node = this.outputElement\n if (!node) {\n return\n }\n\n if (!this.markdown) {\n node.innerHTML = ''\n return\n }\n const renderer = new marked.Renderer()\n if (this.renderer) {\n this.renderer(renderer)\n }\n const data = this.markdown\n const opts: MarkedOptions = {\n renderer,\n breaks: this.breaks,\n pedantic: this.pedantic,\n gfm: true,\n }\n let out = marked(data, opts) as string\n if (this.sanitize) {\n if (this.sanitizer) {\n out = this.sanitizer(out)\n } else {\n const result = DOMPurify.sanitize(out)\n if (typeof result === 'string') {\n out = result\n } else {\n // @ts-expect-error Sometimes the result is an object!\n out = result.toString()\n }\n }\n }\n node.innerHTML = out\n this.dispatchEvent(new Event('markedrendercomplete'))\n }\n\n /**\n * Un-indents the markdown source that will be rendered.\n */\n unindent(text?: string): string {\n if (!text) {\n return ''\n }\n const lines = text.replace(/\\t/g, ' ').split('\\n')\n const indent = lines.reduce((prev: number | null, line: string): number | null => {\n if (/^\\s*$/.test(line)) {\n return prev // Completely ignore blank lines.\n }\n const match = line.match(/^(\\s*)/)\n if (!match) {\n return prev\n }\n\n const lineIndent = match[0].length\n if (prev === null) {\n return lineIndent\n }\n\n return lineIndent < prev ? lineIndent : prev\n }, null)\n\n if (indent === null) {\n return text\n }\n\n return lines.map((l) => l.substring(indent)).join('\\n')\n }\n\n /**\n * Fired when the XHR finishes loading\n */\n protected async requestMarkdown(url: string): Promise<void> {\n try {\n const response = await fetch(url, {\n headers: { accept: 'text/markdown' },\n })\n const { status } = response\n if (status === 0 || (status >= 200 && status < 300)) {\n this.sanitize = !this.disableRemoteSanitization\n this.markdown = await response.text()\n this.dispatchEvent(new Event('markedloaded'))\n } else {\n throw new Error('Unable to download the data')\n }\n } catch (e) {\n this.handleError(e as Error)\n }\n }\n\n /**\n * Fired when an error is received while fetching remote markdown content.\n */\n protected handleError(e: Error): void {\n const evt = new CustomEvent('markedloaderror', {\n composed: true,\n bubbles: true,\n cancelable: true,\n detail: e,\n })\n this.dispatchEvent(evt)\n if (!evt.defaultPrevented) {\n this.markdown = 'Failed loading markdown source'\n }\n }\n\n protected scriptAttributeHandler(mutation: MutationRecord[]): void {\n if (mutation[0].attributeName !== 'src') {\n return\n }\n const elm = this.markdownElement\n if (elm) {\n this.requestMarkdown(elm.src)\n }\n }\n\n override render(): TemplateResult {\n return html`<slot name=\"markdown-html\"><div id=\"content\"></div></slot>`\n }\n}\n"]}
|
package/package.json
CHANGED
|
@@ -171,6 +171,7 @@ export default class Autocomplete extends LitElement {
|
|
|
171
171
|
if (!this.id) {
|
|
172
172
|
this.id = `autocomplete-${Math.random().toString(36).substring(2, 15)}`
|
|
173
173
|
}
|
|
174
|
+
this.classList.add(this.id)
|
|
174
175
|
}
|
|
175
176
|
|
|
176
177
|
override disconnectedCallback(): void {
|
|
@@ -283,12 +284,6 @@ export default class Autocomplete extends LitElement {
|
|
|
283
284
|
this.inputRef.addEventListener('input', this.handleInput)
|
|
284
285
|
this.inputRef.addEventListener('keydown', this.handleKeydown as EventListener)
|
|
285
286
|
this.inputRef.addEventListener('blur', this.handleInputBlur)
|
|
286
|
-
|
|
287
|
-
// Apply initial filtering if suggestions are already present
|
|
288
|
-
if (this.suggestionsRef) {
|
|
289
|
-
this.suggestionsRef.style.setProperty('position-anchor', `--${this.inputId}`)
|
|
290
|
-
this.filterSuggestions((this.inputRef as HTMLInputElement).value || '')
|
|
291
|
-
}
|
|
292
287
|
}
|
|
293
288
|
|
|
294
289
|
/**
|
|
@@ -303,10 +298,6 @@ export default class Autocomplete extends LitElement {
|
|
|
303
298
|
this.suggestionsRef.popover = 'manual'
|
|
304
299
|
this.suggestionsRef.tabIndex = -1 // Prevent direct focus
|
|
305
300
|
|
|
306
|
-
if (this.inputId) {
|
|
307
|
-
this.suggestionsRef.style.setProperty('position-anchor', `--${this.inputId}`)
|
|
308
|
-
}
|
|
309
|
-
|
|
310
301
|
this.suggestionsRef.addEventListener('select', this.handleSuggestionSelect as EventListener)
|
|
311
302
|
// The `List` dispatches `itemschange` when the slot changes, so we can listen to it.
|
|
312
303
|
this.suggestionsRef.addEventListener('itemschange', this.handleSuggestionsSlotChange)
|
|
@@ -562,31 +553,35 @@ export default class Autocomplete extends LitElement {
|
|
|
562
553
|
}
|
|
563
554
|
|
|
564
555
|
protected override render(): TemplateResult {
|
|
565
|
-
const { id, positionArea } = this
|
|
556
|
+
const { id, positionArea, inputId } = this
|
|
557
|
+
/*
|
|
558
|
+
position-try-fallbacks:
|
|
559
|
+
flip-block,
|
|
560
|
+
flip-inline,
|
|
561
|
+
flip-block flip-inline;
|
|
562
|
+
*/
|
|
566
563
|
return html`
|
|
567
564
|
<style>
|
|
568
|
-
|
|
565
|
+
.${id} {
|
|
569
566
|
display: inline-block;
|
|
570
567
|
|
|
571
568
|
[popover] {
|
|
572
569
|
border: none;
|
|
573
570
|
margin: 0;
|
|
574
|
-
position-area: ${positionArea};
|
|
575
|
-
position-try-fallbacks:
|
|
576
|
-
flip-block,
|
|
577
|
-
flip-inline,
|
|
578
|
-
flip-block flip-inline;
|
|
579
|
-
width: anchor-size(width);
|
|
580
571
|
|
|
581
572
|
box-shadow: var(--md-sys-elevation-1);
|
|
582
573
|
border-radius: var(--md-sys-shape-corner-medium);
|
|
583
574
|
|
|
575
|
+
position-area: ${positionArea};
|
|
576
|
+
position-anchor: --${inputId};
|
|
577
|
+
|
|
584
578
|
overflow: auto;
|
|
585
579
|
/* We try 100% and then vendor options which are more accurate */
|
|
586
580
|
height: 100%;
|
|
587
581
|
height: -webkit-fill-available;
|
|
588
582
|
height: -moz-available;
|
|
589
583
|
max-height: max-content;
|
|
584
|
+
width: anchor-size(width);
|
|
590
585
|
}
|
|
591
586
|
|
|
592
587
|
[popover]:not(:popover-open) {
|
|
@@ -154,8 +154,8 @@ export default class MarkedHighlight extends LitElement {
|
|
|
154
154
|
return child || (this.shadowRoot?.querySelector('#content') as HTMLElement | null)
|
|
155
155
|
}
|
|
156
156
|
|
|
157
|
-
protected override
|
|
158
|
-
super.
|
|
157
|
+
protected override willUpdate(cp: PropertyValues<this>): void {
|
|
158
|
+
super.willUpdate(cp)
|
|
159
159
|
if (
|
|
160
160
|
cp.has('markdown') ||
|
|
161
161
|
cp.has('sanitizer') ||
|
|
@@ -177,7 +177,21 @@ export default class MarkedHighlight extends LitElement {
|
|
|
177
177
|
this.renderMarkdown()
|
|
178
178
|
return
|
|
179
179
|
}
|
|
180
|
+
}
|
|
181
|
+
|
|
182
|
+
override connectedCallback(): void {
|
|
183
|
+
super.connectedCallback()
|
|
184
|
+
this.attachedValue = true
|
|
185
|
+
this.processScript()
|
|
186
|
+
this.renderMarkdown()
|
|
187
|
+
}
|
|
188
|
+
|
|
189
|
+
override disconnectedCallback(): void {
|
|
190
|
+
super.disconnectedCallback()
|
|
191
|
+
this.attachedValue = false
|
|
192
|
+
}
|
|
180
193
|
|
|
194
|
+
protected async processScript(): Promise<void> {
|
|
181
195
|
// Use the Markdown from the first `<script>` descendant whose MIME type
|
|
182
196
|
// starts with "text/markdown". Script elements beyond the first are
|
|
183
197
|
// ignored.
|
|
@@ -199,17 +213,6 @@ export default class MarkedHighlight extends LitElement {
|
|
|
199
213
|
observer.observe(script, { attributes: true })
|
|
200
214
|
}
|
|
201
215
|
|
|
202
|
-
override connectedCallback(): void {
|
|
203
|
-
super.connectedCallback()
|
|
204
|
-
this.attachedValue = true
|
|
205
|
-
this.renderMarkdown()
|
|
206
|
-
}
|
|
207
|
-
|
|
208
|
-
override disconnectedCallback(): void {
|
|
209
|
-
super.disconnectedCallback()
|
|
210
|
-
this.attachedValue = false
|
|
211
|
-
}
|
|
212
|
-
|
|
213
216
|
/**
|
|
214
217
|
* Renders `markdown` into this element's DOM.
|
|
215
218
|
*
|
|
@@ -83,14 +83,15 @@ describe('AutocompleteInput', () => {
|
|
|
83
83
|
await el.updateComplete
|
|
84
84
|
await nextFrame() // Allow for internal state updates
|
|
85
85
|
|
|
86
|
-
const input = getSlottedInput(el)
|
|
87
|
-
const suggestions = getSlottedSuggestions(el)
|
|
86
|
+
const input = getSlottedInput(el)!
|
|
87
|
+
const suggestions = getSlottedSuggestions(el)!
|
|
88
88
|
|
|
89
|
-
expect(input
|
|
89
|
+
expect(input.id).to.match(/^autocomplete-input-/)
|
|
90
90
|
// @ts-expect-error _inputId is a protected member
|
|
91
91
|
const internalInputId = el.inputId
|
|
92
|
-
expect(input
|
|
93
|
-
|
|
92
|
+
expect(input.style.getPropertyValue('anchor-name')).to.equal(`--${internalInputId}`, 'input has anchor name')
|
|
93
|
+
const anchorValue = getComputedStyle(suggestions).getPropertyValue('position-anchor')
|
|
94
|
+
expect(anchorValue).to.equal(`--${internalInputId}`, 'suggestions element has position-anchor')
|
|
94
95
|
})
|
|
95
96
|
|
|
96
97
|
it('popover is initially closed', async () => {
|
|
@@ -388,7 +389,8 @@ describe('AutocompleteInput', () => {
|
|
|
388
389
|
const slottedSuggestions = getSlottedSuggestions(el)
|
|
389
390
|
expect(slottedSuggestions).to.equal(suggestionsEl)
|
|
390
391
|
expect(suggestionsEl.popover).to.equal('manual')
|
|
391
|
-
|
|
392
|
+
const anchorValue = getComputedStyle(suggestionsEl).getPropertyValue('position-anchor')
|
|
393
|
+
expect(anchorValue).to.equal(`--${input.id}`)
|
|
392
394
|
})
|
|
393
395
|
|
|
394
396
|
it('re-filters when suggestion items change (via itemschange event)', async () => {
|