@limetech/lime-elements 40.10.0 → 40.11.0

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.
Files changed (34) hide show
  1. package/CHANGELOG.md +14 -0
  2. package/dist/cjs/lime-elements.cjs.js +1 -1
  3. package/dist/cjs/limel-hotkey_4.cjs.entry.js +229 -13
  4. package/dist/cjs/limel-side-panel.cjs.entry.js +67 -22
  5. package/dist/cjs/loader.cjs.js +1 -1
  6. package/dist/collection/components/hotkey/get-hotkey-aria-label.js +14 -0
  7. package/dist/collection/components/hotkey/hotkey.js +3 -5
  8. package/dist/collection/components/side-panel/side-panel.css +176 -1
  9. package/dist/collection/components/side-panel/side-panel.js +197 -22
  10. package/dist/collection/components/side-panel/side-panel.types.js +1 -0
  11. package/dist/collection/components/tooltip/description-registry.js +57 -0
  12. package/dist/collection/components/tooltip/get-description.js +42 -0
  13. package/dist/collection/components/tooltip/tooltip.js +53 -11
  14. package/dist/collection/interface.js +1 -0
  15. package/dist/collection/util/get-focus-target.js +69 -0
  16. package/dist/esm/lime-elements.js +1 -1
  17. package/dist/esm/limel-hotkey_4.entry.js +229 -13
  18. package/dist/esm/limel-side-panel.entry.js +67 -22
  19. package/dist/esm/loader.js +1 -1
  20. package/dist/lime-elements/lime-elements.esm.js +1 -1
  21. package/dist/lime-elements/p-1a5478e3.entry.js +1 -0
  22. package/dist/lime-elements/p-82c65f70.entry.js +1 -0
  23. package/dist/types/components/hotkey/get-hotkey-aria-label.d.ts +8 -0
  24. package/dist/types/components/side-panel/side-panel.d.ts +89 -8
  25. package/dist/types/components/side-panel/side-panel.types.d.ts +83 -0
  26. package/dist/types/components/tooltip/description-registry.d.ts +21 -0
  27. package/dist/types/components/tooltip/get-description.d.ts +13 -0
  28. package/dist/types/components/tooltip/tooltip.d.ts +11 -3
  29. package/dist/types/components.d.ts +221 -10
  30. package/dist/types/interface.d.ts +1 -0
  31. package/dist/types/util/get-focus-target.d.ts +14 -0
  32. package/package.json +3 -3
  33. package/dist/lime-elements/p-566750e5.entry.js +0 -1
  34. package/dist/lime-elements/p-a373013f.entry.js +0 -1
@@ -0,0 +1,83 @@
1
+ import { Color } from '../../global/shared-types/color.types';
2
+ import { Icon, IconName } from '../../global/shared-types/icon.types';
3
+ /**
4
+ * One panel in the stack of a side panel.
5
+ *
6
+ * @beta
7
+ */
8
+ export interface SidePanelEntry {
9
+ /**
10
+ * Heading of the panel.
11
+ */
12
+ heading: string;
13
+ /**
14
+ * Second line below the heading.
15
+ */
16
+ subheading?: string;
17
+ /**
18
+ * Icon shown next to the heading.
19
+ */
20
+ icon?: IconName | Icon;
21
+ /**
22
+ * Background color of the header. When it is set, the heading and the
23
+ * subheading are white, with a text shadow, so that they are easier to
24
+ * read on the color. Use a color that is dark enough for white text.
25
+ */
26
+ color?: Color;
27
+ }
28
+ /**
29
+ * A button in the toolbar of a side panel.
30
+ *
31
+ * @beta
32
+ */
33
+ export interface SidePanelAction {
34
+ /**
35
+ * The kind of button.
36
+ */
37
+ type: SidePanelActionType;
38
+ /**
39
+ * Label of the button. Shown as a tooltip and used as the accessible name.
40
+ */
41
+ label: string;
42
+ /**
43
+ * Identifies the action in the `selectAction` event. Defaults to `type`.
44
+ */
45
+ id?: string;
46
+ /**
47
+ * Additional text in the tooltip, below the label. For example the name
48
+ * of what the action opens.
49
+ */
50
+ helperLabel?: string;
51
+ /**
52
+ * If set, the action is a link to this URL. The user can then open it in
53
+ * a new tab, like any other link. `selectAction` is still emitted. To
54
+ * handle the navigation in another way, call `preventDefault` on its
55
+ * `event`, but only for a plain click with the primary button: `button` is
56
+ * `0`, and `metaKey`, `ctrlKey`, `shiftKey` and `altKey` are `false`. Let
57
+ * the browser handle all other clicks, so that the user can still open the
58
+ * link in a new tab.
59
+ */
60
+ href?: string;
61
+ }
62
+ /**
63
+ * Detail of the `selectAction` event of a side panel.
64
+ *
65
+ * @beta
66
+ */
67
+ export interface SidePanelActionSelect {
68
+ /**
69
+ * The `id` of the clicked action, or its `type` if it has no `id`.
70
+ */
71
+ id: string;
72
+ /**
73
+ * The click event.
74
+ */
75
+ event: MouseEvent;
76
+ }
77
+ /**
78
+ * The kinds of buttons that can be used as actions in a side panel.
79
+ *
80
+ * @beta
81
+ */
82
+ export type SidePanelActionType = 'newTab' | 'expand';
83
+ //# sourceMappingURL=side-panel.types.d.ts.map
@@ -0,0 +1,21 @@
1
+ /**
2
+ * Set the `aria-description` of an element on behalf of an owner. The
3
+ * description that the element had before is kept, for when the last owner
4
+ * stops describing it.
5
+ *
6
+ * @param element
7
+ * @param owner
8
+ * @param text
9
+ */
10
+ export declare function setDescription(element: Element, owner: object, text: string): void;
11
+ /**
12
+ * Stop describing an element on behalf of an owner. The text of the owner
13
+ * that described it most recently stays, and when none is left, the
14
+ * description that the element had before is put back. Nothing is changed
15
+ * if the attribute has been changed by someone else.
16
+ *
17
+ * @param element
18
+ * @param owner
19
+ */
20
+ export declare function clearDescription(element: Element, owner: object): void;
21
+ //# sourceMappingURL=description-registry.d.ts.map
@@ -0,0 +1,13 @@
1
+ /**
2
+ * Get the text that a screen reader should read as the description of the
3
+ * element that a tooltip describes. The label and the helper label are left
4
+ * out when they only repeat the name of the element, or the text of one of
5
+ * its parts, so that they are not read twice.
6
+ *
7
+ * @param element
8
+ * @param label
9
+ * @param helperLabel
10
+ * @param hotkey
11
+ */
12
+ export declare function getDescription(element: HTMLElement, label: string, helperLabel?: string, hotkey?: string): string;
13
+ //# sourceMappingURL=get-description.d.ts.map
@@ -43,14 +43,19 @@ export declare class Tooltip {
43
43
  elementId: string;
44
44
  /**
45
45
  * Short descriptive text of the owner element.
46
+ * Screen readers read it as a part of the description of the element,
47
+ * unless it only repeats the name that the element already has.
46
48
  */
47
49
  label: string;
48
50
  /**
49
51
  * Additional helper text for the element.
52
+ * Screen readers read it as a part of the description of the element.
50
53
  */
51
54
  helperLabel?: string;
52
55
  /**
53
56
  * Keyboard shortcut to visualize inside the tooltip, e.g. `"ctrl+f"`.
57
+ * Screen readers read it, written out in words, as a part of the
58
+ * description of the element.
54
59
  * Display-only: the tooltip does not listen for the keystroke.
55
60
  * Catching the hotkey is the consumer's responsibility.
56
61
  */
@@ -67,14 +72,17 @@ export declare class Tooltip {
67
72
  private host;
68
73
  private open;
69
74
  private portalId;
70
- private tooltipId;
71
75
  private ownerElement;
76
+ private describedElement?;
77
+ private latestUpdate;
72
78
  private tooltipTimer;
73
79
  constructor();
74
- connectedCallback(): void;
80
+ connectedCallback(): Promise<void>;
75
81
  disconnectedCallback(): void;
82
+ protected watchDescription(): Promise<void>;
76
83
  render(): JSX.Element;
77
- private setOwnerAriaDescribedby;
84
+ private updateDescription;
85
+ private restoreDescription;
78
86
  private addListeners;
79
87
  private removeListeners;
80
88
  private showTooltip;
@@ -49,6 +49,7 @@ import { ContentType } from "./components/text-editor/prosemirror-adapter/editor
49
49
  import { EditorImage, EditorMetadata, ImageInserter, InlineImages, TriggerCharacter, TriggerEventDetail } from "./components/text-editor/text-editor.types";
50
50
  import { EditorUiType } from "./components/text-editor/types";
51
51
  import { Option } from "./components/select/option.types";
52
+ import { SidePanelAction, SidePanelActionSelect, SidePanelEntry } from "./components/side-panel/side-panel.types";
52
53
  import { SpinnerSize } from "./components/spinner/spinner.types";
53
54
  import { Tab } from "./components/tab-bar/tab.types";
54
55
  import { Column, ColumnAggregate, ColumnSorter, RowData, RowReorderEvent, TableParams } from "./components/table/table.types";
@@ -98,6 +99,7 @@ export { ContentType } from "./components/text-editor/prosemirror-adapter/editor
98
99
  export { EditorImage, EditorMetadata, ImageInserter, InlineImages, TriggerCharacter, TriggerEventDetail } from "./components/text-editor/text-editor.types";
99
100
  export { EditorUiType } from "./components/text-editor/types";
100
101
  export { Option } from "./components/select/option.types";
102
+ export { SidePanelAction, SidePanelActionSelect, SidePanelEntry } from "./components/side-panel/side-panel.types";
101
103
  export { SpinnerSize } from "./components/spinner/spinner.types";
102
104
  export { Tab } from "./components/tab-bar/tab.types";
103
105
  export { Column, ColumnAggregate, ColumnSorter, RowData, RowReorderEvent, TableParams } from "./components/table/table.types";
@@ -3605,7 +3607,7 @@ export namespace Components {
3605
3607
  }
3606
3608
  /**
3607
3609
  * A resizable panel that is displayed on top of the right side of the page.
3608
- * The content is placed in the default slot, below a toolbar with a close button.
3610
+ * The content is placed in the default slot, below a toolbar and a header.
3609
3611
  * The panel is positioned relative to its nearest positioned ancestor. Set
3610
3612
  * `position: relative` on that element. Use `--side-panel-top-inset`,
3611
3613
  * `--side-panel-right-inset` and `--side-panel-bottom-inset` to keep parts of
@@ -3620,12 +3622,63 @@ export namespace Components {
3620
3622
  * The user can resize the panel by dragging its left edge, or with the arrow
3621
3623
  * keys. The panel emits `changeWidth` when a resize is finished.
3622
3624
  * See the examples for how closing and resizing work in detail.
3625
+ * ## Header
3626
+ * The header shows the heading, subheading and icon of the last entry in
3627
+ * `stack`. When the entry has a `color`, the header gets that background color,
3628
+ * and the headings are white with a text shadow. When `stack` is empty, the
3629
+ * panel has no header.
3630
+ * Put controls for the header, for example a follow button or a menu, in the
3631
+ * `header-actions` slot. They are shown at the right end of the header. When
3632
+ * `stack` is empty, there is no header, and the slot content is not shown.
3633
+ * The slot is for small controls. It is at most half as wide as the header,
3634
+ * and at most as tall as the heading and subheading together. Larger content
3635
+ * is cut off, so that the header keeps its size.
3636
+ * The slot content is not tied to an entry in `stack`. When the last entry
3637
+ * changes, the consumer must also change the slot content.
3638
+ * The slot content keeps its own colors. Use `--side-panel-header-text-color`
3639
+ * to match the text color of the header. It is white when the header has a
3640
+ * `color`. It can also be used as the `color` of an `Icon`.
3641
+ * ## Actions
3642
+ * The toolbar has a close button on the left. Other buttons are set with
3643
+ * `actions`, and are shown on the right. The `type` of an action decides its
3644
+ * icon. When the user clicks an action, the panel emits `selectAction` with the
3645
+ * `id` of the action and the click event. The consumer decides what the action
3646
+ * does.
3647
+ * An action with an `href` is a link, so the user can open it in a new tab.
3648
+ * To handle the navigation in another way, for example with the router of the
3649
+ * application, call `preventDefault` on the click event in `selectAction`. Do
3650
+ * this only for a plain click with the primary button. Let the browser handle
3651
+ * all other clicks, so that Ctrl-click and Cmd-click still open the link in a
3652
+ * new tab:
3653
+ * ```ts
3654
+ * function handleSelectAction(event: CustomEvent<SidePanelActionSelect>) {
3655
+ * const click = event.detail.event;
3656
+ * const isPlainClick =
3657
+ * click.button === 0 &&
3658
+ * !click.metaKey &&
3659
+ * !click.ctrlKey &&
3660
+ * !click.shiftKey &&
3661
+ * !click.altKey;
3662
+ * if (!isPlainClick) {
3663
+ * return;
3664
+ * }
3665
+ * click.preventDefault();
3666
+ * router.navigate(event.detail.id);
3667
+ * }
3668
+ * ```
3623
3669
  * @exampleComponent limel-example-side-panel-basic
3624
3670
  * @exampleComponent limel-example-side-panel-insets
3625
3671
  * @exampleComponent limel-example-side-panel-escape
3672
+ * @exampleComponent limel-example-side-panel-actions
3673
+ * @exampleComponent limel-example-side-panel-header-actions
3626
3674
  * @private
3627
3675
  */
3628
3676
  interface LimelSidePanel {
3677
+ /**
3678
+ * Buttons in the toolbar, to the right of the close button.
3679
+ * @default []
3680
+ */
3681
+ "actions": SidePanelAction[];
3629
3682
  /**
3630
3683
  * Label of the close button. Shown as a tooltip and used as the accessible name.
3631
3684
  * @default 'Close'
@@ -3645,6 +3698,11 @@ export namespace Components {
3645
3698
  * @default 'Resize'
3646
3699
  */
3647
3700
  "resizeLabel": string;
3701
+ /**
3702
+ * The panels in the stack, outermost first. The last entry is the panel that is displayed. Its heading, subheading and icon are shown in the header.
3703
+ * @default []
3704
+ */
3705
+ "stack": SidePanelEntry[];
3648
3706
  }
3649
3707
  /**
3650
3708
  * @exampleComponent limel-example-slider-basic
@@ -4239,15 +4297,15 @@ export namespace Components {
4239
4297
  */
4240
4298
  "elementId": string;
4241
4299
  /**
4242
- * Additional helper text for the element.
4300
+ * Additional helper text for the element. Screen readers read it as a part of the description of the element.
4243
4301
  */
4244
4302
  "helperLabel"?: string;
4245
4303
  /**
4246
- * Keyboard shortcut to visualize inside the tooltip, e.g. `"ctrl+f"`. Display-only: the tooltip does not listen for the keystroke. Catching the hotkey is the consumer's responsibility.
4304
+ * Keyboard shortcut to visualize inside the tooltip, e.g. `"ctrl+f"`. Screen readers read it, written out in words, as a part of the description of the element. Display-only: the tooltip does not listen for the keystroke. Catching the hotkey is the consumer's responsibility.
4247
4305
  */
4248
4306
  "hotkey"?: string;
4249
4307
  /**
4250
- * Short descriptive text of the owner element.
4308
+ * Short descriptive text of the owner element. Screen readers read it as a part of the description of the element, unless it only repeats the name that the element already has.
4251
4309
  */
4252
4310
  "label": string;
4253
4311
  /**
@@ -6590,11 +6648,12 @@ declare global {
6590
6648
  };
6591
6649
  interface HTMLLimelSidePanelElementEventMap {
6592
6650
  "close": void;
6651
+ "selectAction": SidePanelActionSelect;
6593
6652
  "changeWidth": number;
6594
6653
  }
6595
6654
  /**
6596
6655
  * A resizable panel that is displayed on top of the right side of the page.
6597
- * The content is placed in the default slot, below a toolbar with a close button.
6656
+ * The content is placed in the default slot, below a toolbar and a header.
6598
6657
  * The panel is positioned relative to its nearest positioned ancestor. Set
6599
6658
  * `position: relative` on that element. Use `--side-panel-top-inset`,
6600
6659
  * `--side-panel-right-inset` and `--side-panel-bottom-inset` to keep parts of
@@ -6609,9 +6668,55 @@ declare global {
6609
6668
  * The user can resize the panel by dragging its left edge, or with the arrow
6610
6669
  * keys. The panel emits `changeWidth` when a resize is finished.
6611
6670
  * See the examples for how closing and resizing work in detail.
6671
+ * ## Header
6672
+ * The header shows the heading, subheading and icon of the last entry in
6673
+ * `stack`. When the entry has a `color`, the header gets that background color,
6674
+ * and the headings are white with a text shadow. When `stack` is empty, the
6675
+ * panel has no header.
6676
+ * Put controls for the header, for example a follow button or a menu, in the
6677
+ * `header-actions` slot. They are shown at the right end of the header. When
6678
+ * `stack` is empty, there is no header, and the slot content is not shown.
6679
+ * The slot is for small controls. It is at most half as wide as the header,
6680
+ * and at most as tall as the heading and subheading together. Larger content
6681
+ * is cut off, so that the header keeps its size.
6682
+ * The slot content is not tied to an entry in `stack`. When the last entry
6683
+ * changes, the consumer must also change the slot content.
6684
+ * The slot content keeps its own colors. Use `--side-panel-header-text-color`
6685
+ * to match the text color of the header. It is white when the header has a
6686
+ * `color`. It can also be used as the `color` of an `Icon`.
6687
+ * ## Actions
6688
+ * The toolbar has a close button on the left. Other buttons are set with
6689
+ * `actions`, and are shown on the right. The `type` of an action decides its
6690
+ * icon. When the user clicks an action, the panel emits `selectAction` with the
6691
+ * `id` of the action and the click event. The consumer decides what the action
6692
+ * does.
6693
+ * An action with an `href` is a link, so the user can open it in a new tab.
6694
+ * To handle the navigation in another way, for example with the router of the
6695
+ * application, call `preventDefault` on the click event in `selectAction`. Do
6696
+ * this only for a plain click with the primary button. Let the browser handle
6697
+ * all other clicks, so that Ctrl-click and Cmd-click still open the link in a
6698
+ * new tab:
6699
+ * ```ts
6700
+ * function handleSelectAction(event: CustomEvent<SidePanelActionSelect>) {
6701
+ * const click = event.detail.event;
6702
+ * const isPlainClick =
6703
+ * click.button === 0 &&
6704
+ * !click.metaKey &&
6705
+ * !click.ctrlKey &&
6706
+ * !click.shiftKey &&
6707
+ * !click.altKey;
6708
+ * if (!isPlainClick) {
6709
+ * return;
6710
+ * }
6711
+ * click.preventDefault();
6712
+ * router.navigate(event.detail.id);
6713
+ * }
6714
+ * ```
6612
6715
  * @exampleComponent limel-example-side-panel-basic
6613
6716
  * @exampleComponent limel-example-side-panel-insets
6614
6717
  * @exampleComponent limel-example-side-panel-escape
6718
+ * @exampleComponent limel-example-side-panel-actions
6719
+ * @exampleComponent limel-example-side-panel-header-actions
6615
6720
  * @private
6616
6721
  */
6617
6722
  interface HTMLLimelSidePanelElement extends Components.LimelSidePanel, HTMLStencilElement {
@@ -10818,7 +10923,7 @@ declare namespace LocalJSX {
10818
10923
  }
10819
10924
  /**
10820
10925
  * A resizable panel that is displayed on top of the right side of the page.
10821
- * The content is placed in the default slot, below a toolbar with a close button.
10926
+ * The content is placed in the default slot, below a toolbar and a header.
10822
10927
  * The panel is positioned relative to its nearest positioned ancestor. Set
10823
10928
  * `position: relative` on that element. Use `--side-panel-top-inset`,
10824
10929
  * `--side-panel-right-inset` and `--side-panel-bottom-inset` to keep parts of
@@ -10833,12 +10938,63 @@ declare namespace LocalJSX {
10833
10938
  * The user can resize the panel by dragging its left edge, or with the arrow
10834
10939
  * keys. The panel emits `changeWidth` when a resize is finished.
10835
10940
  * See the examples for how closing and resizing work in detail.
10941
+ * ## Header
10942
+ * The header shows the heading, subheading and icon of the last entry in
10943
+ * `stack`. When the entry has a `color`, the header gets that background color,
10944
+ * and the headings are white with a text shadow. When `stack` is empty, the
10945
+ * panel has no header.
10946
+ * Put controls for the header, for example a follow button or a menu, in the
10947
+ * `header-actions` slot. They are shown at the right end of the header. When
10948
+ * `stack` is empty, there is no header, and the slot content is not shown.
10949
+ * The slot is for small controls. It is at most half as wide as the header,
10950
+ * and at most as tall as the heading and subheading together. Larger content
10951
+ * is cut off, so that the header keeps its size.
10952
+ * The slot content is not tied to an entry in `stack`. When the last entry
10953
+ * changes, the consumer must also change the slot content.
10954
+ * The slot content keeps its own colors. Use `--side-panel-header-text-color`
10955
+ * to match the text color of the header. It is white when the header has a
10956
+ * `color`. It can also be used as the `color` of an `Icon`.
10957
+ * ## Actions
10958
+ * The toolbar has a close button on the left. Other buttons are set with
10959
+ * `actions`, and are shown on the right. The `type` of an action decides its
10960
+ * icon. When the user clicks an action, the panel emits `selectAction` with the
10961
+ * `id` of the action and the click event. The consumer decides what the action
10962
+ * does.
10963
+ * An action with an `href` is a link, so the user can open it in a new tab.
10964
+ * To handle the navigation in another way, for example with the router of the
10965
+ * application, call `preventDefault` on the click event in `selectAction`. Do
10966
+ * this only for a plain click with the primary button. Let the browser handle
10967
+ * all other clicks, so that Ctrl-click and Cmd-click still open the link in a
10968
+ * new tab:
10969
+ * ```ts
10970
+ * function handleSelectAction(event: CustomEvent<SidePanelActionSelect>) {
10971
+ * const click = event.detail.event;
10972
+ * const isPlainClick =
10973
+ * click.button === 0 &&
10974
+ * !click.metaKey &&
10975
+ * !click.ctrlKey &&
10976
+ * !click.shiftKey &&
10977
+ * !click.altKey;
10978
+ * if (!isPlainClick) {
10979
+ * return;
10980
+ * }
10981
+ * click.preventDefault();
10982
+ * router.navigate(event.detail.id);
10983
+ * }
10984
+ * ```
10836
10985
  * @exampleComponent limel-example-side-panel-basic
10837
10986
  * @exampleComponent limel-example-side-panel-insets
10838
10987
  * @exampleComponent limel-example-side-panel-escape
10988
+ * @exampleComponent limel-example-side-panel-actions
10989
+ * @exampleComponent limel-example-side-panel-header-actions
10839
10990
  * @private
10840
10991
  */
10841
10992
  interface LimelSidePanel {
10993
+ /**
10994
+ * Buttons in the toolbar, to the right of the close button.
10995
+ * @default []
10996
+ */
10997
+ "actions"?: SidePanelAction[];
10842
10998
  /**
10843
10999
  * Label of the close button. Shown as a tooltip and used as the accessible name.
10844
11000
  * @default 'Close'
@@ -10861,11 +11017,20 @@ declare namespace LocalJSX {
10861
11017
  * Emitted when the close button is clicked, or when Escape is pressed and `closeOnEscape` is `true`.
10862
11018
  */
10863
11019
  "onClose"?: (event: LimelSidePanelCustomEvent<void>) => void;
11020
+ /**
11021
+ * Emitted when an action in the toolbar is clicked. The detail has the `id` of the action, or its `type` if it has no `id`, and the click event.
11022
+ */
11023
+ "onSelectAction"?: (event: LimelSidePanelCustomEvent<SidePanelActionSelect>) => void;
10864
11024
  /**
10865
11025
  * Label of the resize handle. Used as the accessible name.
10866
11026
  * @default 'Resize'
10867
11027
  */
10868
11028
  "resizeLabel"?: string;
11029
+ /**
11030
+ * The panels in the stack, outermost first. The last entry is the panel that is displayed. Its heading, subheading and icon are shown in the header.
11031
+ * @default []
11032
+ */
11033
+ "stack"?: SidePanelEntry[];
10869
11034
  }
10870
11035
  /**
10871
11036
  * @exampleComponent limel-example-slider-basic
@@ -11562,15 +11727,15 @@ declare namespace LocalJSX {
11562
11727
  */
11563
11728
  "elementId": string;
11564
11729
  /**
11565
- * Additional helper text for the element.
11730
+ * Additional helper text for the element. Screen readers read it as a part of the description of the element.
11566
11731
  */
11567
11732
  "helperLabel"?: string;
11568
11733
  /**
11569
- * Keyboard shortcut to visualize inside the tooltip, e.g. `"ctrl+f"`. Display-only: the tooltip does not listen for the keystroke. Catching the hotkey is the consumer's responsibility.
11734
+ * Keyboard shortcut to visualize inside the tooltip, e.g. `"ctrl+f"`. Screen readers read it, written out in words, as a part of the description of the element. Display-only: the tooltip does not listen for the keystroke. Catching the hotkey is the consumer's responsibility.
11570
11735
  */
11571
11736
  "hotkey"?: string;
11572
11737
  /**
11573
- * Short descriptive text of the owner element.
11738
+ * Short descriptive text of the owner element. Screen readers read it as a part of the description of the element, unless it only repeats the name that the element already has.
11574
11739
  */
11575
11740
  "label": string;
11576
11741
  /**
@@ -13595,7 +13760,7 @@ declare module "@stencil/core" {
13595
13760
  "limel-shortcut": LocalJSX.IntrinsicElements["limel-shortcut"] & JSXBase.HTMLAttributes<HTMLLimelShortcutElement>;
13596
13761
  /**
13597
13762
  * A resizable panel that is displayed on top of the right side of the page.
13598
- * The content is placed in the default slot, below a toolbar with a close button.
13763
+ * The content is placed in the default slot, below a toolbar and a header.
13599
13764
  * The panel is positioned relative to its nearest positioned ancestor. Set
13600
13765
  * `position: relative` on that element. Use `--side-panel-top-inset`,
13601
13766
  * `--side-panel-right-inset` and `--side-panel-bottom-inset` to keep parts of
@@ -13610,9 +13775,55 @@ declare module "@stencil/core" {
13610
13775
  * The user can resize the panel by dragging its left edge, or with the arrow
13611
13776
  * keys. The panel emits `changeWidth` when a resize is finished.
13612
13777
  * See the examples for how closing and resizing work in detail.
13778
+ * ## Header
13779
+ * The header shows the heading, subheading and icon of the last entry in
13780
+ * `stack`. When the entry has a `color`, the header gets that background color,
13781
+ * and the headings are white with a text shadow. When `stack` is empty, the
13782
+ * panel has no header.
13783
+ * Put controls for the header, for example a follow button or a menu, in the
13784
+ * `header-actions` slot. They are shown at the right end of the header. When
13785
+ * `stack` is empty, there is no header, and the slot content is not shown.
13786
+ * The slot is for small controls. It is at most half as wide as the header,
13787
+ * and at most as tall as the heading and subheading together. Larger content
13788
+ * is cut off, so that the header keeps its size.
13789
+ * The slot content is not tied to an entry in `stack`. When the last entry
13790
+ * changes, the consumer must also change the slot content.
13791
+ * The slot content keeps its own colors. Use `--side-panel-header-text-color`
13792
+ * to match the text color of the header. It is white when the header has a
13793
+ * `color`. It can also be used as the `color` of an `Icon`.
13794
+ * ## Actions
13795
+ * The toolbar has a close button on the left. Other buttons are set with
13796
+ * `actions`, and are shown on the right. The `type` of an action decides its
13797
+ * icon. When the user clicks an action, the panel emits `selectAction` with the
13798
+ * `id` of the action and the click event. The consumer decides what the action
13799
+ * does.
13800
+ * An action with an `href` is a link, so the user can open it in a new tab.
13801
+ * To handle the navigation in another way, for example with the router of the
13802
+ * application, call `preventDefault` on the click event in `selectAction`. Do
13803
+ * this only for a plain click with the primary button. Let the browser handle
13804
+ * all other clicks, so that Ctrl-click and Cmd-click still open the link in a
13805
+ * new tab:
13806
+ * ```ts
13807
+ * function handleSelectAction(event: CustomEvent<SidePanelActionSelect>) {
13808
+ * const click = event.detail.event;
13809
+ * const isPlainClick =
13810
+ * click.button === 0 &&
13811
+ * !click.metaKey &&
13812
+ * !click.ctrlKey &&
13813
+ * !click.shiftKey &&
13814
+ * !click.altKey;
13815
+ * if (!isPlainClick) {
13816
+ * return;
13817
+ * }
13818
+ * click.preventDefault();
13819
+ * router.navigate(event.detail.id);
13820
+ * }
13821
+ * ```
13613
13822
  * @exampleComponent limel-example-side-panel-basic
13614
13823
  * @exampleComponent limel-example-side-panel-insets
13615
13824
  * @exampleComponent limel-example-side-panel-escape
13825
+ * @exampleComponent limel-example-side-panel-actions
13826
+ * @exampleComponent limel-example-side-panel-header-actions
13616
13827
  * @private
13617
13828
  */
13618
13829
  "limel-side-panel": LocalJSX.IntrinsicElements["limel-side-panel"] & JSXBase.HTMLAttributes<HTMLLimelSidePanelElement>;
@@ -35,6 +35,7 @@ export * from './components/picker/searcher.types';
35
35
  export * from './components/picker/value.types';
36
36
  export * from './components/progress-flow/progress-flow.types';
37
37
  export * from './components/select/option.types';
38
+ export * from './components/side-panel/side-panel.types';
38
39
  export * from './components/spinner/spinner.types';
39
40
  export * from './components/tab-bar/tab.types';
40
41
  export * from './components/tab-panel/tab-panel.types';
@@ -0,0 +1,14 @@
1
+ /**
2
+ * Get the element that a screen reader describes for the owner element of a
3
+ * tooltip. That is the owner itself if it can be focused, otherwise the first
4
+ * element that can be focused inside it, also inside shadow roots. A disabled
5
+ * control is only used when there is nothing that can be focused, and if
6
+ * there is no control at all, the owner itself is used.
7
+ *
8
+ * An element that passes the focus on to an element in its shadow root is
9
+ * never used itself, since the screen reader lands on the element inside.
10
+ *
11
+ * @param owner
12
+ */
13
+ export declare function getFocusTarget(owner: HTMLElement): Promise<HTMLElement>;
14
+ //# sourceMappingURL=get-focus-target.d.ts.map
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@limetech/lime-elements",
3
- "version": "40.10.0",
3
+ "version": "40.11.0",
4
4
  "description": "Lime Elements",
5
5
  "author": "Lime Technologies",
6
6
  "license": "Apache-2.0",
@@ -85,7 +85,7 @@
85
85
  "html-escaper": "^3.0.3",
86
86
  "jsonlint-mod": "^1.7.6",
87
87
  "jsx-dom": "^8.1.6",
88
- "kompendium": "npm:@limetech/kompendium@^1.3.0",
88
+ "kompendium": "npm:@limetech/kompendium@^1.4.1",
89
89
  "lodash-es": "^4.17.23",
90
90
  "material-components-web": "^13.0.0",
91
91
  "mdast-util-to-markdown": "^2.2.0",
@@ -94,7 +94,7 @@
94
94
  "number-abbreviate": "^2.0.0",
95
95
  "parse-css-color": "^0.2.1",
96
96
  "postal-mime": "^4.0.5",
97
- "prettier": "^3.9.9",
97
+ "prettier": "^3.9.10",
98
98
  "prosemirror-example-setup": "^1.2.3",
99
99
  "prosemirror-markdown": "^1.13.8",
100
100
  "prosemirror-model": ">=1.25.12",
@@ -1 +0,0 @@
1
- import{r as e,c as i,h as t,H as s,a as o}from"./p-BU9IJqli.js";import{E as r}from"./p-Bu6-QXrA.js";import{c as a}from"./p-BrjD-ITe.js";const n=[];function l(e){e.stopPropagation()}const d=class{constructor(t){e(this,t),this.close=i(this,"close",7),this.changeWidth=i(this,"changeWidth",7),this.closeLabel="Close",this.resizeLabel="Resize",this.closeOnEscape=!0,this.closeButtonId=a(),this.setBody=e=>{this.body=e,this.stopContentEventsInBody()},this.restoreFocus=()=>{const e=!document.activeElement||document.activeElement===document.body;if(this.host.isConnected||!e)return;const i=this.focusedBefore;this.focusedBefore=void 0,(null==i?void 0:i.isConnected)&&i.focus()},this.setPanel=e=>{this.panel=e},this.setMinLimit=e=>{this.minLimit=e},this.setMaxLimit=e=>{this.maxLimit=e},this.handleKeyDown=e=>{this.closeOnEscape&&e.key===r&&!e.defaultPrevented&&this.isLastOpened()&&(e.preventDefault(),this.close.emit())},this.handleChangeSize=e=>{this.rememberWidthBeforeResize(),this.setWidth(e.detail)},this.handleEndResize=()=>{if(!this.isResizing())return;const e=this.widthBeforeResize;this.widthBeforeResize=void 0,this.keepClampedWidth(),this.updateWidthRange(),this.emitWidthIfChanged(e)},this.handleSizeChange=e=>{e.every(this.isMeasured)||this.updateWidthRange()},this.isMeasured=e=>{var i;return e.target===this.panel&&Math.round(e.borderBoxSize[0].inlineSize)===(null===(i=this.widthRange)||void 0===i?void 0:i.now)},this.updateWidthRange=()=>{this.isResizing()||(this.widthRange=this.measureWidthRange())},this.handleClickClose=()=>{this.close.emit()}}connectedCallback(){n.push(this),window.addEventListener("keydown",this.handleKeyDown),this.rememberFocusedElement(),this.observeWidth()}componentDidLoad(){this.observeWidth(),this.moveFocusIntoPanel()}disconnectedCallback(){this.widthBeforeResize=void 0,this.stopObservingWidth(),window.removeEventListener("keydown",this.handleKeyDown),this.removeFromOpenPanels(),queueMicrotask(this.restoreFocus)}render(){return t(s,{key:"1c18f40fb45731bdf157d651d4e649446de5230b"},t("section",{key:"e8b41bded39732750ae3db9b1daf14dc742e1cb7",ref:this.setPanel,role:"dialog","aria-label":this.label,tabindex:"-1"},this.renderHandle(),t("div",{key:"3cba5523e0cbe45fa328daaa40136c063a8c3ac3",class:"content"},t("div",{key:"b5cbc1260b4e6f31ac789179ab4b5a0281b9133b",class:"toolbar"},this.renderCloseButton()),this.renderBody())),t("span",{key:"5fe872f05a6cc49027f84d71a765baa59a53adb9","data-limit":"min",ref:this.setMinLimit}),t("span",{key:"5042e7437e61ae5308e13b1a30f5df24747e2cdf","data-limit":"max",ref:this.setMaxLimit}))}renderCloseButton(){return t("button",{class:"close",id:this.closeButtonId,"aria-label":this.closeLabel,onClick:this.handleClickClose},t("limel-icon",{name:"multiply","aria-hidden":"true"}),t("limel-tooltip",{elementId:this.closeButtonId,label:this.closeLabel}))}renderHandle(){var e,i,s;return t("limel-resize-handle",{class:"handle",label:this.resizeLabel,value:null===(e=this.widthRange)||void 0===e?void 0:e.now,min:null===(i=this.widthRange)||void 0===i?void 0:i.min,max:null===(s=this.widthRange)||void 0===s?void 0:s.max,onChangeSize:this.handleChangeSize,onEndResize:this.handleEndResize})}renderBody(){return t("div",{class:"body",ref:this.setBody},t("slot",null))}stopContentEventsInBody(){var e,i;null===(e=this.body)||void 0===e||e.addEventListener("close",l),null===(i=this.body)||void 0===i||i.addEventListener("changeWidth",l)}stopContentEventAtHost(e){e.target!==this.host&&e.stopImmediatePropagation()}moveFocusIntoPanel(){this.panel.focus({preventScroll:!0})}rememberFocusedElement(){const e=function(){var e;let i=document.activeElement;for(;null===(e=null==i?void 0:i.shadowRoot)||void 0===e?void 0:e.activeElement;)i=i.shadowRoot.activeElement;return i}();e&&e!==document.body&&(this.focusedBefore=e)}removeFromOpenPanels(){const e=n.indexOf(this);-1!==e&&n.splice(e,1)}isLastOpened(){return n.at(-1)===this}setWidth(e){this.panel.style.width=`${e}px`}rememberWidthBeforeResize(){this.isResizing()||(this.widthBeforeResize=this.currentWidth())}isResizing(){return void 0!==this.widthBeforeResize}keepClampedWidth(){this.setWidth(this.currentWidth())}emitWidthIfChanged(e){const i=this.currentWidth();i!==e&&this.changeWidth.emit(i)}observeWidth(){if(this.stopObservingWidth(),this.panel){this.widthObserver=new ResizeObserver(this.handleSizeChange);for(const e of[this.panel,this.minLimit,this.maxLimit])e&&this.widthObserver.observe(e)}}stopObservingWidth(){var e;null===(e=this.widthObserver)||void 0===e||e.disconnect(),this.widthObserver=void 0}measureWidthRange(){const e=this.minLimit.offsetWidth,i=Math.max(e,this.maxLimit.offsetWidth);return{now:Math.round(this.currentWidth()),min:Math.round(e),max:Math.round(i)}}currentWidth(){return this.panel.offsetWidth}get host(){return o(this)}};d.style='@charset "UTF-8";:host(limel-side-panel){--_side-panel-width:var(--side-panel-width, 37.5rem);--_side-panel-min-width:var(--side-panel-min-width, 25rem);--_side-panel-top-inset:var(--side-panel-top-inset, 0px);--_side-panel-right-inset:var(--side-panel-right-inset, 0px);--_side-panel-bottom-inset:var(--side-panel-bottom-inset, 0px);--_side-panel-z-index:var(--side-panel-z-index, 6)}@keyframes show-side-panel{0%{transform:translate3d(12.5rem, 0, 0) scale(0.95);opacity:0}60%{opacity:1}100%{transform:translate3d(0, 0, 0) scale(1)}}section{position:absolute;z-index:var(--_side-panel-z-index);top:var(--_side-panel-top-inset);right:var(--_side-panel-right-inset);bottom:var(--_side-panel-bottom-inset);margin:0.5rem;display:flex;flex-direction:column;isolation:isolate;width:var(--_side-panel-width);min-width:min(var(--_side-panel-min-width), 100% - 1rem);max-width:min(100% - 1rem - 3rem, 60%);max-height:100%;border-radius:1rem;box-shadow:var(--shadow-depth-64);transform-origin:left center;transition:background-color 0.5s ease, transform 0.3s ease, opacity 0.2s ease, right 0.2s ease;animation:show-side-panel 0.46s cubic-bezier(0.08, 0.54, 0.06, 1.11) forwards}section:focus{outline:none}@media (prefers-reduced-motion){section{animation:none;transition:none}}.content{display:flex;flex-direction:column;flex-grow:1;min-height:0;overflow:hidden;border-radius:1rem;background-color:rgb(var(--contrast-100))}.toolbar{flex-shrink:0;display:flex;align-items:center;gap:0.25rem;box-sizing:border-box;min-height:2.375rem;padding:0.25rem 0.125rem;background-color:rgb(var(--contrast-300))}.close{appearance:none;background:none;border:none;padding:0;margin:0;font:inherit;color:inherit;text-align:inherit;transition:color var(--limel-clickable-transition-speed, 0.4s) ease, background-color var(--limel-clickable-transition-speed, 0.4s) ease, box-shadow var(--limel-clickable-transform-speed, 0.4s) ease, transform var(--limel-clickable-transform-speed, 0.4s) var(--limel-clickable-transform-timing-function, ease);cursor:pointer;color:var(--limel-theme-on-surface-color);background-color:transparent}.close:hover,.close:focus,.close:focus-visible{will-change:color, background-color, box-shadow, transform}.close:hover,.close:focus-visible{transform:translate3d(0, 0.01rem, 0);color:var(--limel-theme-on-surface-color);background-color:var(--lime-elevated-surface-background-color)}.close:hover{box-shadow:var(--button-shadow-hovered)}.close:active{--limel-clickable-transform-timing-function:cubic-bezier( 0.83, -0.15, 0.49, 1.16 );transform:translate3d(0, 0.05rem, 0);box-shadow:var(--button-shadow-pressed)}.close:hover,.close:active{--limel-clickable-transition-speed:0.2s;--limel-clickable-transform-speed:0.16s}.close:focus{outline:none}.close:focus-visible{outline:none;box-shadow:var(--shadow-depth-8-focused)}.close{isolation:isolate;position:relative;display:flex;justify-content:center;align-items:center;width:1.875rem;height:1.875rem;border-radius:50%}.close limel-icon{width:1.25rem;transition:transform 0.2s ease, color 0.2s ease}.close:before,.close:after{content:"";position:absolute;z-index:-1;inset:0;border-radius:50%;opacity:0;transition-delay:0.1s}.close:before{transition:transform 0.3s ease, opacity 0.3s ease;background-color:rgb(var(--color-orange-dark))}.close:after{transition:transform 0.6s ease, opacity 0.6s ease;background-color:rgb(var(--color-orange-light))}.close:hover limel-icon{color:rgb(var(--color-white));transform:scale(0.7) rotate(90deg)}.close:hover:before{opacity:1;transform:scale(0.4)}.close:hover:after{opacity:0.4;transform:scale(0.6)}.body{flex-grow:1;min-height:0;display:flex;flex-direction:column;overflow:hidden auto}.handle{position:absolute;z-index:1;top:calc(2.375rem + 0.5rem);bottom:1rem;left:calc(0.5rem / -2);width:0.5rem}[data-limit]{position:absolute;visibility:hidden;pointer-events:none;height:0}[data-limit=min]{width:min(var(--_side-panel-min-width), 100% - 1rem)}[data-limit=max]{width:min(100% - 1rem - 3rem, 60%)}';export{d as limel_side_panel}