@ui-doc/html-renderer 0.3.0 → 1.0.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 (102) hide show
  1. package/README.md +586 -151
  2. package/dist/HtmlCurlyBraceLexer.d.ts +4 -1
  3. package/dist/HtmlRenderer.d.ts +5 -5
  4. package/dist/InlineReader.d.ts +3 -2
  5. package/dist/{types/lexer.d.ts → Lexer.types.d.ts} +8 -5
  6. package/dist/NodeParser.d.ts +3 -2
  7. package/dist/{types/parser.d.ts → Parser.types.d.ts} +8 -8
  8. package/dist/{types/base.d.ts → Primitive.types.d.ts} +1 -1
  9. package/dist/{types/reader.d.ts → Reader.types.d.ts} +9 -7
  10. package/dist/Renderer.types.d.ts +14 -0
  11. package/dist/TemplateLoader.d.ts +3 -2
  12. package/dist/{types/token.d.ts → Token.types.d.ts} +1 -1
  13. package/dist/assets/services/expand.d.ts +19 -0
  14. package/dist/assets/ui-doc.cjs +283 -9
  15. package/dist/assets/ui-doc.cjs.map +1 -1
  16. package/dist/assets/ui-doc.css +1169 -250
  17. package/dist/assets/ui-doc.css.map +1 -1
  18. package/dist/assets/ui-doc.min.css +9 -1
  19. package/dist/assets/ui-doc.min.js +1 -1
  20. package/dist/assets/ui-doc.mjs +283 -9
  21. package/dist/assets/ui-doc.mjs.map +1 -1
  22. package/dist/assets/utils/delay.d.ts +1 -0
  23. package/dist/assets/utils/dom.d.ts +31 -0
  24. package/dist/assets/utils/select.d.ts +12 -0
  25. package/dist/index.cjs +161 -126
  26. package/dist/index.cjs.map +1 -1
  27. package/dist/index.d.ts +6 -1
  28. package/dist/index.mjs +160 -126
  29. package/dist/index.mjs.map +1 -1
  30. package/dist/nodes/CommentNode.d.ts +2 -1
  31. package/dist/nodes/Node.d.ts +1 -1
  32. package/dist/nodes/TemplateNode.d.ts +2 -1
  33. package/dist/nodes/index.d.ts +4 -2
  34. package/dist/nodes/tags/debug.d.ts +2 -1
  35. package/dist/nodes/tags/for.d.ts +4 -3
  36. package/dist/nodes/tags/if.d.ts +5 -4
  37. package/dist/nodes/tags/index.d.ts +1 -1
  38. package/dist/nodes/tags/page.d.ts +2 -1
  39. package/dist/nodes/tags/partial.d.ts +2 -1
  40. package/dist/nodes/tags/var.d.ts +2 -1
  41. package/dist/utils/index.d.ts +1 -1
  42. package/package.json +32 -29
  43. package/scripts/app.ts +5 -3
  44. package/scripts/{src → services}/example.ts +3 -3
  45. package/scripts/services/expand.ts +214 -0
  46. package/scripts/{src → services}/sidebar.ts +4 -3
  47. package/scripts/utils/delay.ts +12 -0
  48. package/scripts/utils/dom.ts +77 -0
  49. package/scripts/utils/select.ts +46 -0
  50. package/styles/01_resets/initial.css +8 -3
  51. package/styles/01_resets/root/color.css +19 -0
  52. package/styles/01_resets/root/font.css +28 -0
  53. package/styles/01_resets/root/space.css +30 -0
  54. package/styles/01_resets/root/witdh.css +12 -0
  55. package/styles/01_resets/root.css +61 -23
  56. package/styles/01_resets/typography.css +105 -8
  57. package/styles/02_utils/background.css +14 -0
  58. package/styles/02_utils/control.css +41 -0
  59. package/styles/02_utils/margin.css +150 -0
  60. package/styles/02_utils/padding.css +134 -0
  61. package/styles/02_utils/width.css +39 -0
  62. package/styles/03_components/button.css +42 -0
  63. package/styles/03_components/colors.css +7 -19
  64. package/styles/03_components/container.css +16 -0
  65. package/styles/03_components/example-markup.css +1 -6
  66. package/styles/03_components/grid-auto.css +49 -0
  67. package/styles/03_components/icons.css +7 -19
  68. package/styles/03_components/navigation/burger-control.css +75 -0
  69. package/styles/03_components/{nav → navigation}/list.css +9 -11
  70. package/styles/03_components/navigation/main.css +102 -0
  71. package/styles/03_components/spaces.css +8 -7
  72. package/styles/04_layout/body.css +22 -0
  73. package/styles/04_layout/inline-code.css +6 -0
  74. package/styles/04_layout/page.css +73 -0
  75. package/styles/index.css +58 -17
  76. package/templates/layouts/default.html +4 -6
  77. package/templates/layouts/example.html +1 -1
  78. package/templates/pages/default.html +13 -13
  79. package/templates/pages/index.html +9 -3
  80. package/templates/partials/code.html +1 -1
  81. package/templates/partials/colors.html +2 -2
  82. package/templates/partials/content.html +1 -1
  83. package/templates/partials/icons.html +3 -3
  84. package/templates/partials/nav-main.html +19 -8
  85. package/templates/partials/section.html +1 -1
  86. package/templates/partials/spaces.html +2 -2
  87. package/LICENSE.md +0 -9
  88. package/dist/assets/src/utils.d.ts +0 -2
  89. package/dist/types/index.d.ts +0 -6
  90. package/dist/types/renderer.d.ts +0 -14
  91. package/scripts/src/utils.ts +0 -20
  92. package/styles/02_objects/background.css +0 -7
  93. package/styles/02_objects/control.css +0 -25
  94. package/styles/02_objects/margin.css +0 -44
  95. package/styles/02_objects/padding.css +0 -44
  96. package/styles/02_objects/text.css +0 -3
  97. package/styles/02_objects/width.css +0 -16
  98. package/styles/03_components/nav/main.css +0 -39
  99. package/styles/03_components/text-flow.css +0 -5
  100. package/styles/04_layouts/page.css +0 -70
  101. /package/dist/assets/{src → services}/example.d.ts +0 -0
  102. /package/dist/assets/{src → services}/sidebar.d.ts +0 -0
@@ -1,4 +1,7 @@
1
- import type { Lexer, PositiveInteger, Reader, Token, TokenBoolean, TokenComment, TokenIdentifier, TokenNumber, TokenOperator, TokenReturn, TokenString, TokenTemplate, TokenTypeIdentifier } from './types';
1
+ import type { Lexer } from './Lexer.types';
2
+ import type { PositiveInteger } from './Primitive.types';
3
+ import type { Reader } from './Reader.types';
4
+ import type { Token, TokenBoolean, TokenComment, TokenIdentifier, TokenNumber, TokenOperator, TokenReturn, TokenString, TokenTemplate, TokenTypeIdentifier } from './Token.types';
2
5
  export declare class HtmlCurlyBraceLexer implements Lexer {
3
6
  protected reader: Reader;
4
7
  protected currentTokens: (Token | undefined)[];
@@ -1,7 +1,7 @@
1
- import type { GenerateContext } from '@ui-doc/core';
1
+ import type { GenerateContext, GenerateExampleContext } from '@ui-doc/core';
2
2
  import type { Node } from './nodes';
3
- import type { RenderContext, Renderer, SourceInput } from './types';
4
- import type { Parser } from './types/parser';
3
+ import type { Parser } from './Parser.types';
4
+ import type { RenderContext, Renderer, SourceInput } from './Renderer.types';
5
5
  export declare class HtmlRenderer implements Renderer {
6
6
  protected parser: Parser;
7
7
  protected layouts: Record<string, Node>;
@@ -12,10 +12,10 @@ export declare class HtmlRenderer implements Renderer {
12
12
  addPartial(name: string, partial: SourceInput): this;
13
13
  addPage(name: string, page: SourceInput): this;
14
14
  protected parse(input: SourceInput): Node;
15
- generate(context: GenerateContext, layout?: string): string;
15
+ generate(context: GenerateContext | GenerateExampleContext, layout?: string): string;
16
16
  page(name: string, context: RenderContext): string;
17
17
  partial(name: string, context?: RenderContext): string;
18
18
  protected render(rootNode: Node, context: RenderContext): string;
19
- protected generateContext(context: GenerateContext): RenderContext;
19
+ protected generateContext(context: GenerateContext | GenerateExampleContext): RenderContext;
20
20
  protected makeAttributes(attrs?: Record<string, string>): string;
21
21
  }
@@ -1,4 +1,5 @@
1
- import type { PositiveInteger, Reader } from './types';
1
+ import type { PositiveInteger } from './Primitive.types';
2
+ import type { Reader } from './Reader.types';
2
3
  export declare class InlineReader implements Reader {
3
4
  protected input: string;
4
5
  protected source: string;
@@ -6,7 +7,7 @@ export declare class InlineReader implements Reader {
6
7
  protected currentPos: number;
7
8
  protected currentContent: string;
8
9
  constructor(input: string, source?: string);
9
- peak(k?: PositiveInteger): string;
10
+ peek(k?: PositiveInteger): string;
10
11
  consume(k?: PositiveInteger): string;
11
12
  isEof(): boolean;
12
13
  debug(): {
@@ -1,4 +1,6 @@
1
- import type { PositiveInteger, Reader, TokenReturn } from './index';
1
+ import type { PositiveInteger } from './Primitive.types';
2
+ import type { Reader } from './Reader.types';
3
+ import type { TokenReturn } from './Token.types';
2
4
  export interface Lexer {
3
5
  /**
4
6
  * Get the next token /next k-th token.
@@ -7,17 +9,18 @@ export interface Lexer {
7
9
  * @param {PositiveInteger} k
8
10
  * @returns {Token | undefined} next token or undefined if there are no more tokens.
9
11
  */
10
- peek<T extends PositiveInteger = 1>(k?: T): TokenReturn<T>;
12
+ peek: <T extends PositiveInteger = 1>(k?: T) => TokenReturn<T>;
11
13
  /**
12
14
  * Get the next token /next k-th token, and remove it from the token stream.
13
- * This means, calling the consume() method multiple times will return a new token at each invocation.
15
+ * This means, calling the consume() method multiple times will return a new token at each
16
+ * invocation.
14
17
  * @param {PositiveInteger} k
15
18
  * @returns {Token | undefined} next token or undefined if there are no more tokens.
16
19
  */
17
- consume<T extends PositiveInteger = 1>(k?: T): TokenReturn<T>;
20
+ consume: <T extends PositiveInteger = 1>(k?: T) => TokenReturn<T>;
18
21
  /**
19
22
  * Get the debug information about the current state of the lexer.
20
23
  * @returns {object} debug information
21
24
  */
22
- debug(): ReturnType<Reader['debug']>;
25
+ debug: () => ReturnType<Reader['debug']>;
23
26
  }
@@ -1,7 +1,8 @@
1
- import { HtmlCurlyBraceLexer } from './HtmlCurlyBraceLexer';
2
1
  import type { TagNode } from './nodes';
2
+ import type { Parser, TagNodeParse } from './Parser.types';
3
+ import type { Reader } from './Reader.types';
4
+ import { HtmlCurlyBraceLexer } from './HtmlCurlyBraceLexer';
3
5
  import { Node } from './nodes/Node';
4
- import type { Parser, Reader, TagNodeParse } from './types';
5
6
  export declare class NodeParser implements Parser {
6
7
  protected tags: Record<string, TagNodeParse>;
7
8
  static init(): NodeParser;
@@ -1,13 +1,13 @@
1
- import type { Node, TagNode } from '../nodes';
2
- import type { Reader } from './reader';
3
- import type { Token } from './token';
1
+ import type { Node, TagNode } from './nodes';
2
+ import type { Reader } from './Reader.types';
3
+ import type { TokenValue } from './Token.types';
4
4
  export interface TagNodeParse {
5
5
  identifier: string;
6
6
  example: string;
7
7
  hasContent: boolean;
8
- parse(): {
9
- addToken(token: Token): void;
10
- create(): TagNode;
8
+ parse: () => {
9
+ addToken: (token: TokenValue) => void;
10
+ create: () => TagNode;
11
11
  };
12
12
  }
13
13
  export interface Parser {
@@ -16,10 +16,10 @@ export interface Parser {
16
16
  * @param {Reader} reader
17
17
  * @returns {Node} AST
18
18
  */
19
- parse(reader: Reader): Node;
19
+ parse: (reader: Reader) => Node;
20
20
  /**
21
21
  * Register a tag parser.
22
22
  * @param {TagNodeParse} tag
23
23
  */
24
- registerTagParser(tag: TagNodeParse): this;
24
+ registerTagParser: (tag: TagNodeParse) => this;
25
25
  }
@@ -1 +1 @@
1
- export type PositiveInteger<T extends number = number> = `${T}` extends '0' | `-${any}` | `${any}.${any}` ? never : T;
1
+ export type PositiveInteger<T extends number = number> = `${T}` extends '0' | `-${string}` | `${string}.${string}` ? never : T;
@@ -1,32 +1,34 @@
1
- import type { PositiveInteger } from './base';
1
+ import type { PositiveInteger } from './Primitive.types';
2
2
  export interface Reader {
3
3
  /**
4
4
  * Get the next character / next k-th character from the input.
5
- * This is used to look ahead the characters without consuming/removing them from the input stream.
5
+ * This is used to look ahead the characters without consuming/removing them from the input
6
+ * stream.
6
7
  * Calling the peek() method more than once will return the same character.
7
8
  *
8
9
  * @param {PositiveInteger} k number
9
10
  * @returns {string} next character
10
11
  */
11
- peak(k?: PositiveInteger): string;
12
+ peek: (k?: PositiveInteger) => string;
12
13
  /**
13
14
  * Get the next character /next k-th token from the input, and remove it from the input.
14
- * This means, calling the consume() method multiple times will return a new character at each invocation.
15
+ * This means, calling the consume() method multiple times will return a new character at each
16
+ * invocation.
15
17
  *
16
18
  * @param {PositiveInteger} k
17
19
  * @returns {string} next character
18
20
  */
19
- consume(k?: PositiveInteger): string;
21
+ consume: (k?: PositiveInteger) => string;
20
22
  /**
21
23
  * Check if the input stream is empty.
22
24
  * @returns {boolean} true if the input stream is empty, false otherwise.
23
25
  */
24
- isEof(): boolean;
26
+ isEof: () => boolean;
25
27
  /**
26
28
  * Get the debug information about the current state of the reader.
27
29
  * @returns {object} debug information
28
30
  */
29
- debug(): {
31
+ debug: () => {
30
32
  source: string;
31
33
  line: PositiveInteger;
32
34
  pos: PositiveInteger;
@@ -0,0 +1,14 @@
1
+ import type { Renderer as CoreRenderer } from '@ui-doc/core';
2
+ import type { Reader } from './Reader.types';
3
+ export type RenderContext = Record<string, unknown>;
4
+ export type SourceInput = {
5
+ source: string;
6
+ content: string;
7
+ } | Reader;
8
+ export interface Renderer extends CoreRenderer {
9
+ addLayout: (name: string, layout: SourceInput) => this;
10
+ addPartial: (name: string, partial: SourceInput) => this;
11
+ addPage: (name: string, page: SourceInput) => this;
12
+ page: (name: string, context: RenderContext) => string;
13
+ partial: (name: string, context?: RenderContext) => string;
14
+ }
@@ -1,9 +1,10 @@
1
1
  import type { FileSystem } from '@ui-doc/core';
2
2
  import type { HtmlRenderer } from './HtmlRenderer';
3
3
  export declare class TemplateLoader {
4
- static load({ renderer, fileSystem, templateBasePath, }: {
4
+ static readonly TEMPLATES_PACKAGE: string;
5
+ static load({ renderer, fileSystem, templatePath, }: {
5
6
  renderer: HtmlRenderer;
6
7
  fileSystem: FileSystem;
7
- templateBasePath?: string;
8
+ templatePath: string;
8
9
  }): Promise<void>;
9
10
  }
@@ -1,4 +1,4 @@
1
- import type { PositiveInteger } from './base';
1
+ import type { PositiveInteger } from './Primitive.types';
2
2
  export type TokenTypeIdentifier = 'tag-identifier' | 'identifier';
3
3
  export type TokenTagType = 'tag-open' | 'tag-close' | 'tag-end' | 'tag-separator';
4
4
  export type TokenType = 'comment' | 'template' | 'operator' | 'number' | 'string' | 'boolean' | TokenTypeIdentifier | TokenTagType;
@@ -0,0 +1,19 @@
1
+ /**
2
+ * Initialize expandable/collapsable elements by using the
3
+ * [aria-expanded](https://developer.mozilla.org/en-US/docs/Web/Accessibility/ARIA/Attributes/aria-expanded) attribute.
4
+ *
5
+ * When an element with the `aria-expanded` attribute is clicked, the value of the attribute will
6
+ * be toggled between `true` and `false`.
7
+ *
8
+ * @location functions.expand Expand
9
+ * @example
10
+ * <style>
11
+ * button::after {
12
+ * content: ' ' attr(aria-expanded);
13
+ * }
14
+ * </style>
15
+ * <button aria-expanded="false">Expanded:</button>
16
+ * @code
17
+ * <button aria-expanded="false">Expanded:</button>
18
+ */
19
+ export declare function initExpand(): void;
@@ -38,6 +38,288 @@ function initExample() {
38
38
  });
39
39
  }
40
40
 
41
+ /**
42
+ * Run function when dom is ready
43
+ *
44
+ * @param callback function to run when dom is ready
45
+ */
46
+ function ready(callback) {
47
+ if (document.readyState !== 'loading') {
48
+ callback.call(document);
49
+ }
50
+ else {
51
+ document.addEventListener('DOMContentLoaded', callback);
52
+ }
53
+ }
54
+ /**
55
+ * Animate an element using css animations/transitions. This function will add the necessary
56
+ * classes to the element to trigger the animation.
57
+ * When doing an entering animation following classes will be added:
58
+ * - `[animation-name]-enter-active`
59
+ * - `[animation-name]-enter-from`
60
+ * - `[animation-name]-enter-to`
61
+ * When doing a leaving animation following classes will be added:
62
+ * - `[animation-name]-leave-active`
63
+ * - `[animation-name]-leave-from`
64
+ * - `[animation-name]-leave-to`
65
+ *
66
+ * The animation classes will be removed after the animation is done. If a callback is provided
67
+ * it will be called after the animation is done.
68
+ *
69
+ * The `-active` class will stay on the element until the animation is done. The `-from` class will
70
+ * be removed after the first frame and the `-to`
71
+ * class will be added after the first frame.
72
+ *
73
+ * @param target html element to animate
74
+ * @param animationName animation name to be used
75
+ * @param entering determine if the elements animation should be entering or leaving
76
+ * @param callback to be called after the animation is done
77
+ */
78
+ function animate(target, animationName, entering, callback) {
79
+ const animationState = entering ? 'enter' : 'leave';
80
+ const animateClassActive = `${animationName}-${animationState}-active`;
81
+ const animateClassTo = `${animationName}-${animationState}-to`;
82
+ const animateClassFrom = `${animationName}-${animationState}-from`;
83
+ const afterAnimation = () => {
84
+ target.classList.remove(animateClassTo, animateClassActive);
85
+ target.removeEventListener('animationend', afterAnimation);
86
+ target.removeEventListener('transitionend', afterAnimation);
87
+ if (callback) {
88
+ callback();
89
+ }
90
+ };
91
+ target.addEventListener('animationend', afterAnimation);
92
+ target.addEventListener('transitionend', afterAnimation);
93
+ target.addEventListener('animationcancel', afterAnimation);
94
+ target.addEventListener('transitioncancel', afterAnimation);
95
+ target.classList.add(animateClassActive, animateClassFrom);
96
+ requestAnimationFrame(() => {
97
+ const styles = window.getComputedStyle(target);
98
+ // if the element has no transition or animation we can call the afterAnimation function in the
99
+ // next frame
100
+ if (['all', 'none'].includes(styles.transition) && styles.animationName === 'none') {
101
+ requestAnimationFrame(afterAnimation);
102
+ }
103
+ target.classList.remove(animateClassFrom);
104
+ target.classList.add(animateClassTo);
105
+ });
106
+ }
107
+
108
+ /**
109
+ * Query the first parent element that matches the selector
110
+ *
111
+ * @param element to search in
112
+ * @param selector to be matched
113
+ * @param maxDepth maximum depth to search
114
+ * @returns element that matches the selector
115
+ */
116
+ function queryParentSelector(element, selector, maxDepth = 10) {
117
+ if (maxDepth <= 0 || element === null) {
118
+ return null;
119
+ }
120
+ if (element.matches(selector)) {
121
+ return element;
122
+ }
123
+ return element.parentElement
124
+ ? queryParentSelector(element.parentElement, selector, maxDepth - 1)
125
+ : null;
126
+ }
127
+
128
+ /**
129
+ * Sometimes you need to prevent the user from interacting with other elements while an element
130
+ * is expanded. Then you need the [inert](https://developer.mozilla.org/en-US/docs/Web/HTML/Global_attributes/inert) attribute.
131
+ * You can set the `data-inert` attribute with selectors (comma separated) to control the
132
+ * `inert` attribute of elements matching your selectors.
133
+ * @location functions.expand.with-inerts Expand controlling inert
134
+ * @order 30
135
+ * @example
136
+ * <style>
137
+ * button::after {
138
+ * content: ' ' attr(aria-expanded);
139
+ * }
140
+ * </style>
141
+ * <button aria-expanded="false" aria-controls="target">Expanded:</button>
142
+ * <div id="target" hidden data-inert="[data-inert-controlled],#inert-controlled-2">Controlled Target</div>
143
+ * <div data-inert-controlled=""><button>Button 1.1</button><button>Button 1.2</button></div>
144
+ * <div id="inert-controlled-2"><button>Button 2.1</button><button>Button 2.2</button></div>
145
+ * @code
146
+ * <button aria-expanded="false" aria-controls="target">Expanded:</button>
147
+ * <div id="target" hidden data-inert="[data-inert-controlled],#inert-controlled-2">Controlled Target</div>
148
+ * <div data-inert-controlled="1"><button>Button 1.1</button><button>Button 1.2</button></div>
149
+ * <div id="inert-controlled-2"><button>Button 2.1</button><button>Button 2.2</button></div>
150
+ */
151
+ function toggleInert(target, show) {
152
+ const inertSelector = target.getAttribute('data-inert');
153
+ if (inertSelector === null || inertSelector === '') {
154
+ return;
155
+ }
156
+ inertSelector.split(',').forEach(selector => {
157
+ // if the target is inside an element with the same selector, we don't want to remove the inert attribute
158
+ const activeParentWithSameSelector = !show
159
+ ? queryParentSelector(target.parentElement, `[data-inert="${selector}"],`
160
+ + `[data-inert^="${selector},"],`
161
+ + `[data-inert$=",${selector}"],`
162
+ + `[data-inert*=",${selector},"]`)
163
+ : null;
164
+ if (activeParentWithSameSelector) {
165
+ return;
166
+ }
167
+ document.querySelectorAll(selector).forEach(invertOn => {
168
+ if (show) {
169
+ invertOn.setAttribute('inert', '');
170
+ }
171
+ else {
172
+ invertOn.removeAttribute('inert');
173
+ }
174
+ });
175
+ });
176
+ }
177
+ /**
178
+ * If you want to control a specific aria you can combine [aria-expanded](https://developer.mozilla.org/en-US/docs/Web/Accessibility/ARIA/Attributes/aria-expanded) attribute with [aria-controls](https://developer.mozilla.org/en-US/docs/Web/Accessibility/ARIA/Attributes/aria-controls) attribute.
179
+ *
180
+ * When an element with the `aria-expanded` attribute is clicked, the value of the attribute will be toggled between `true` and `false`. Also the element with the id specified in the `aria-controls` attribute will be toggled between `aria-hidden="true"` and `aria-hidden="false"`. If no `aria-hidden` attribute is present, the `hidden` attribute will be used.`
181
+ *
182
+ * @location functions.expand.with-controls Expand with controls
183
+ * @order 10
184
+ * @example
185
+ * <style>
186
+ * button::after {
187
+ * content: ' ' attr(aria-expanded);
188
+ * }
189
+ * </style>
190
+ * <button aria-expanded="true" aria-controls="target-aria-hidden">Expanded:</button>
191
+ * <div id="target-aria-hidden" aria-hidden="false">Controlled Target</div>
192
+ * <hr>
193
+ * <button aria-expanded="true" aria-controls="target-hidden">Expanded:</button>
194
+ * <div id="target-hidden">Controlled Target</div>
195
+ * @code
196
+ * <button aria-expanded="true" aria-controls="target-aria-hidden">Expanded:</button>
197
+ * <div id="target-aria-hidden" aria-hidden="false">Controlled Target</div>
198
+ * <hr>
199
+ * <button aria-expanded="true" aria-controls="target-hidden">Expanded:</button>
200
+ * <div id="target-hidden">Controlled Target</div>
201
+ */
202
+ /**
203
+ * You can add animations/transitions on the controlled element by adding the `data-animate` attribute with the animation name.
204
+ * The animation name will be used to add the necessary classes to the element to trigger the animation.
205
+ * Please refer to the animate function for more information, what classes will be added and when.
206
+ *
207
+ * @location functions.expand.with-animation Expand with animation
208
+ * @order 20
209
+ * @example
210
+ * <style>
211
+ * .fade-enter-active,
212
+ * .fade-leave-active {
213
+ * transition: opacity 0.5s ease;
214
+ * }
215
+ *
216
+ * .fade-enter-from,
217
+ * .fade-leave-to {
218
+ * opacity: 0;
219
+ * }
220
+ * </style>
221
+ * <button aria-expanded="true" aria-controls="target-hidden">Toggle Controlled Area</button>
222
+ * <div id="target-hidden" data-animate="fade">Controlled Target</div>
223
+ */
224
+ function toggleControlTarget(selector, show, callback) {
225
+ const target = document.querySelector(selector);
226
+ if (!target) {
227
+ return;
228
+ }
229
+ const animationName = target.getAttribute('data-animate');
230
+ const toggleHide = () => {
231
+ if (target.hasAttribute('aria-hidden')) {
232
+ target.setAttribute('aria-hidden', show ? 'false' : 'true');
233
+ }
234
+ else if (show) {
235
+ target.removeAttribute('hidden');
236
+ }
237
+ else {
238
+ target.setAttribute('hidden', '');
239
+ }
240
+ callback();
241
+ };
242
+ if (show) {
243
+ // set tabindex=0 for all elements with tabindex=-1 that are not inside an aria-hidden element
244
+ target
245
+ .querySelectorAll(':scope > [tabindex="-1"], [tabindex="-1"]:not([aria-hidden="true"] [tabindex="-1"], [hidden] [tabindex="-1"])')
246
+ .forEach(el => {
247
+ el.setAttribute('tabindex', '0');
248
+ });
249
+ }
250
+ else {
251
+ // set tabindex=-1 for all elements with tabindex=0
252
+ target.querySelectorAll('[tabindex="0"]').forEach(el => {
253
+ el.setAttribute('tabindex', '-1');
254
+ });
255
+ }
256
+ toggleInert(target, show);
257
+ if (animationName !== null && animationName !== '') {
258
+ if (show) {
259
+ toggleHide();
260
+ animate(target, animationName, show);
261
+ }
262
+ else {
263
+ animate(target, animationName, show, toggleHide);
264
+ }
265
+ }
266
+ else {
267
+ toggleHide();
268
+ }
269
+ }
270
+ /**
271
+ * Initialize expandable/collapsable elements by using the
272
+ * [aria-expanded](https://developer.mozilla.org/en-US/docs/Web/Accessibility/ARIA/Attributes/aria-expanded) attribute.
273
+ *
274
+ * When an element with the `aria-expanded` attribute is clicked, the value of the attribute will
275
+ * be toggled between `true` and `false`.
276
+ *
277
+ * @location functions.expand Expand
278
+ * @example
279
+ * <style>
280
+ * button::after {
281
+ * content: ' ' attr(aria-expanded);
282
+ * }
283
+ * </style>
284
+ * <button aria-expanded="false">Expanded:</button>
285
+ * @code
286
+ * <button aria-expanded="false">Expanded:</button>
287
+ */
288
+ function initExpand() {
289
+ document.querySelectorAll('[aria-expanded]').forEach(expander => {
290
+ const controlTarget = expander.getAttribute('aria-controls');
291
+ const toggle = (e) => {
292
+ const expanded = expander.getAttribute('aria-expanded') === 'true';
293
+ const toggleExpanded = () => {
294
+ expander.setAttribute('aria-expanded', expanded ? 'false' : 'true'); // when expanded we need to set false
295
+ };
296
+ // if data-hide-same-level is set, we need to klick all other expanded elements to close them
297
+ if (expander.parentElement && expander.hasAttribute('data-hide-same-level')) {
298
+ Array.from(expander.parentElement.querySelectorAll(':scope > [aria-expanded="true"]'))
299
+ .filter(el => el !== expander && el !== e.relatedTarget)
300
+ .forEach(sibling => {
301
+ sibling.dispatchEvent(new MouseEvent('click', { bubbles: true, relatedTarget: expander }));
302
+ });
303
+ }
304
+ if (controlTarget !== null && controlTarget !== '') {
305
+ toggleControlTarget(`#${controlTarget}`, !expanded, toggleExpanded);
306
+ }
307
+ else {
308
+ toggleExpanded();
309
+ }
310
+ };
311
+ expander.addEventListener('click', toggle);
312
+ if (controlTarget !== null && controlTarget !== '') {
313
+ // select all controls inside the controlled area that have the same aria-controls attribute
314
+ document
315
+ .querySelectorAll(`#${controlTarget} [aria-controls="${controlTarget}"]`)
316
+ .forEach(control => {
317
+ control.addEventListener('click', toggle);
318
+ });
319
+ }
320
+ });
321
+ }
322
+
41
323
  function createSidebar(sidebar) {
42
324
  const links = {};
43
325
  const observer = new IntersectionObserver(entries => {
@@ -75,16 +357,8 @@ function initSidebar() {
75
357
  });
76
358
  }
77
359
 
78
- function ready(callback) {
79
- if (document.readyState !== 'loading') {
80
- callback();
81
- }
82
- else {
83
- document.addEventListener('DOMContentLoaded', callback);
84
- }
85
- }
86
-
87
360
  ready(() => {
361
+ initExpand();
88
362
  initExample();
89
363
  initSidebar();
90
364
  });
@@ -1 +1 @@
1
- {"version":3,"file":"ui-doc.cjs","sources":["../../../scripts/src/example.ts","../../../scripts/src/sidebar.ts","../../../scripts/src/utils.ts","../../../scripts/app.ts"],"sourcesContent":["export function initExample() {\n document.querySelectorAll<HTMLIFrameElement>('[data-example] > iframe').forEach(iframe => {\n const document = iframe.contentDocument ?? iframe.contentWindow?.document\n\n if (!document) {\n return\n }\n\n const initHeightChange = () => {\n let currentHeight = 0\n const changeHeight = () => {\n if (document.body.scrollHeight === currentHeight) {\n return\n }\n\n currentHeight = document.body.scrollHeight\n iframe.style.height = `${currentHeight}px`\n }\n\n // Initial height change\n changeHeight()\n\n // Use MutationObserver to detect changes in the DOM and change height if required\n const mutationObserver = new MutationObserver(changeHeight)\n\n mutationObserver.observe(document.body, {\n attributes: true,\n childList: true,\n subtree: true,\n })\n\n // Use ResizeObserver to detect changes in the viewport and change height if required\n const resizeObserver = new ResizeObserver(changeHeight)\n\n resizeObserver.observe(document.body)\n }\n\n if (document.readyState === 'complete') {\n initHeightChange()\n } else {\n iframe.addEventListener('load', initHeightChange)\n }\n })\n}\n","function createSidebar(sidebar: HTMLElement) {\n const links: Record<string, HTMLLinkElement> = {}\n const observer = new IntersectionObserver(\n entries => {\n const activeEntries = entries.filter(entry => entry.isIntersecting)\n\n if (activeEntries.length <= 0) {\n return\n }\n\n Object.keys(links).forEach(id => {\n links[id].classList.remove('active')\n })\n\n const activeLink = links[activeEntries[0].target.id]\n\n activeLink.classList.add('active')\n if (activeLink?.parentElement?.parentElement?.parentElement instanceof HTMLLIElement) {\n activeLink.parentElement.parentElement.parentElement\n .querySelector('a')\n ?.classList.add('active')\n }\n },\n {\n root: null,\n rootMargin: '0px 0px -90% 0px',\n threshold: 0.5,\n },\n )\n\n sidebar.querySelectorAll<HTMLLinkElement>('a[href^=\"#\"]').forEach(link => {\n const id = link.href.split('#')[1]\n const target = document.getElementById(id)\n\n if (target) {\n observer.observe(target)\n links[id] = link\n }\n })\n}\n\nexport function initSidebar() {\n document.querySelectorAll('[data-sidebar]').forEach(sidebar => {\n createSidebar(sidebar as HTMLElement)\n })\n}\n","export function ready(callback: () => void) {\n if (document.readyState !== 'loading') {\n callback()\n } else {\n document.addEventListener('DOMContentLoaded', callback)\n }\n}\n\nexport function throttle(callback: (...args: any[]) => void, delay: number) {\n let timerFlag: number | null = null\n\n return (...args: any[]) => {\n if (timerFlag === null) {\n callback(...args)\n timerFlag = window.setTimeout(() => {\n timerFlag = null\n }, delay)\n }\n }\n}\n","import { initExample } from './src/example'\nimport { initSidebar } from './src/sidebar'\nimport { ready } from './src/utils'\n\nready(() => {\n initExample()\n initSidebar()\n})\n"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"ui-doc.cjs","sources":["../../../scripts/services/example.ts","../../../scripts/utils/dom.ts","../../../scripts/utils/select.ts","../../../scripts/services/expand.ts","../../../scripts/services/sidebar.ts","../../../scripts/app.ts"],"sourcesContent":["export function initExample(): void {\n document.querySelectorAll<HTMLIFrameElement>('[data-example] > iframe').forEach(iframe => {\n const document = iframe.contentDocument ?? iframe.contentWindow?.document\n\n if (!document) {\n return\n }\n\n const initHeightChange = (): void => {\n let currentHeight = 0\n const changeHeight = (): void => {\n if (document.body.scrollHeight === currentHeight) {\n return\n }\n\n currentHeight = document.body.scrollHeight\n iframe.style.height = `${currentHeight}px`\n }\n\n // Initial height change\n changeHeight()\n\n // Use MutationObserver to detect changes in the DOM and change height if required\n const mutationObserver = new MutationObserver(changeHeight)\n\n mutationObserver.observe(document.body, {\n attributes: true,\n childList: true,\n subtree: true,\n })\n\n // Use ResizeObserver to detect changes in the viewport and change height if required\n const resizeObserver = new ResizeObserver(changeHeight)\n\n resizeObserver.observe(document.body)\n }\n\n if (document.readyState === 'complete') {\n initHeightChange()\n } else {\n iframe.addEventListener('load', initHeightChange)\n }\n })\n}\n","/**\n * Run function when dom is ready\n *\n * @param callback function to run when dom is ready\n */\nexport function ready(callback: (this: Document) => void): void {\n if (document.readyState !== 'loading') {\n callback.call(document)\n } else {\n document.addEventListener('DOMContentLoaded', callback)\n }\n}\n\n/**\n * Animate an element using css animations/transitions. This function will add the necessary\n * classes to the element to trigger the animation.\n * When doing an entering animation following classes will be added:\n * - `[animation-name]-enter-active`\n * - `[animation-name]-enter-from`\n * - `[animation-name]-enter-to`\n * When doing a leaving animation following classes will be added:\n * - `[animation-name]-leave-active`\n * - `[animation-name]-leave-from`\n * - `[animation-name]-leave-to`\n *\n * The animation classes will be removed after the animation is done. If a callback is provided\n * it will be called after the animation is done.\n *\n * The `-active` class will stay on the element until the animation is done. The `-from` class will\n * be removed after the first frame and the `-to`\n * class will be added after the first frame.\n *\n * @param target html element to animate\n * @param animationName animation name to be used\n * @param entering determine if the elements animation should be entering or leaving\n * @param callback to be called after the animation is done\n */\nexport function animate(\n target: HTMLElement,\n animationName: string,\n entering: boolean,\n callback?: () => void,\n): void {\n const animationState = entering ? 'enter' : 'leave'\n const animateClassActive = `${animationName}-${animationState}-active`\n const animateClassTo = `${animationName}-${animationState}-to`\n const animateClassFrom = `${animationName}-${animationState}-from`\n const afterAnimation = (): void => {\n target.classList.remove(animateClassTo, animateClassActive)\n target.removeEventListener('animationend', afterAnimation)\n target.removeEventListener('transitionend', afterAnimation)\n\n if (callback) {\n callback()\n }\n }\n\n target.addEventListener('animationend', afterAnimation)\n target.addEventListener('transitionend', afterAnimation)\n\n target.addEventListener('animationcancel', afterAnimation)\n target.addEventListener('transitioncancel', afterAnimation)\n\n target.classList.add(animateClassActive, animateClassFrom)\n requestAnimationFrame(() => {\n const styles = window.getComputedStyle(target)\n\n // if the element has no transition or animation we can call the afterAnimation function in the\n // next frame\n if (['all', 'none'].includes(styles.transition) && styles.animationName === 'none') {\n requestAnimationFrame(afterAnimation)\n }\n\n target.classList.remove(animateClassFrom)\n target.classList.add(animateClassTo)\n })\n}\n","/**\n * Query the first parent element that matches the selector\n *\n * @param element to search in\n * @param selector to be matched\n * @param maxDepth maximum depth to search\n * @returns element that matches the selector\n */\n\nexport function queryParentSelector<K extends keyof HTMLElementTagNameMap>(\n element: HTMLElement | null,\n selector: K,\n maxDepth?: number,\n): HTMLElementTagNameMap[K] | null\nexport function queryParentSelector<K extends keyof SVGElementTagNameMap>(\n element: HTMLElement | null,\n selector: K,\n maxDepth?: number,\n): SVGElementTagNameMap[K] | null\nexport function queryParentSelector<K extends keyof MathMLElementTagNameMap>(\n element: HTMLElement | null,\n selectors: K,\n maxDepth?: number,\n): MathMLElementTagNameMap[K] | null\nexport function queryParentSelector<E extends Element = Element>(\n element: HTMLElement | null,\n selector: string,\n maxDepth?: number,\n): E | null\nexport function queryParentSelector(\n element: HTMLElement | null,\n selector: string,\n maxDepth = 10,\n): Element | null {\n if (maxDepth <= 0 || element === null) {\n return null\n }\n\n if (element.matches(selector)) {\n return element as Element\n }\n\n return element.parentElement\n ? queryParentSelector(element.parentElement, selector, maxDepth - 1)\n : null\n}\n","import { animate } from '../utils/dom'\nimport { queryParentSelector } from '../utils/select'\n\n/**\n * Sometimes you need to prevent the user from interacting with other elements while an element\n * is expanded. Then you need the [inert](https://developer.mozilla.org/en-US/docs/Web/HTML/Global_attributes/inert) attribute.\n * You can set the `data-inert` attribute with selectors (comma separated) to control the\n * `inert` attribute of elements matching your selectors.\n * @location functions.expand.with-inerts Expand controlling inert\n * @order 30\n * @example\n * <style>\n * button::after {\n * content: ' ' attr(aria-expanded);\n * }\n * </style>\n * <button aria-expanded=\"false\" aria-controls=\"target\">Expanded:</button>\n * <div id=\"target\" hidden data-inert=\"[data-inert-controlled],#inert-controlled-2\">Controlled Target</div>\n * <div data-inert-controlled=\"\"><button>Button 1.1</button><button>Button 1.2</button></div>\n * <div id=\"inert-controlled-2\"><button>Button 2.1</button><button>Button 2.2</button></div>\n * @code\n * <button aria-expanded=\"false\" aria-controls=\"target\">Expanded:</button>\n * <div id=\"target\" hidden data-inert=\"[data-inert-controlled],#inert-controlled-2\">Controlled Target</div>\n * <div data-inert-controlled=\"1\"><button>Button 1.1</button><button>Button 1.2</button></div>\n * <div id=\"inert-controlled-2\"><button>Button 2.1</button><button>Button 2.2</button></div>\n */\nfunction toggleInert(target: HTMLElement, show: boolean): void {\n const inertSelector = target.getAttribute('data-inert')\n\n if (inertSelector === null || inertSelector === '') {\n return\n }\n\n inertSelector.split(',').forEach(selector => {\n // if the target is inside an element with the same selector, we don't want to remove the inert attribute\n const activeParentWithSameSelector = !show\n ? queryParentSelector(\n target.parentElement,\n `[data-inert=\"${selector}\"],`\n + `[data-inert^=\"${selector},\"],`\n + `[data-inert$=\",${selector}\"],`\n + `[data-inert*=\",${selector},\"]`,\n )\n : null\n\n if (activeParentWithSameSelector) {\n return\n }\n\n document.querySelectorAll(selector).forEach(invertOn => {\n if (show) {\n invertOn.setAttribute('inert', '')\n } else {\n invertOn.removeAttribute('inert')\n }\n })\n })\n}\n\n/**\n * If you want to control a specific aria you can combine [aria-expanded](https://developer.mozilla.org/en-US/docs/Web/Accessibility/ARIA/Attributes/aria-expanded) attribute with [aria-controls](https://developer.mozilla.org/en-US/docs/Web/Accessibility/ARIA/Attributes/aria-controls) attribute.\n *\n * When an element with the `aria-expanded` attribute is clicked, the value of the attribute will be toggled between `true` and `false`. Also the element with the id specified in the `aria-controls` attribute will be toggled between `aria-hidden=\"true\"` and `aria-hidden=\"false\"`. If no `aria-hidden` attribute is present, the `hidden` attribute will be used.`\n *\n * @location functions.expand.with-controls Expand with controls\n * @order 10\n * @example\n * <style>\n * button::after {\n * content: ' ' attr(aria-expanded);\n * }\n * </style>\n * <button aria-expanded=\"true\" aria-controls=\"target-aria-hidden\">Expanded:</button>\n * <div id=\"target-aria-hidden\" aria-hidden=\"false\">Controlled Target</div>\n * <hr>\n * <button aria-expanded=\"true\" aria-controls=\"target-hidden\">Expanded:</button>\n * <div id=\"target-hidden\">Controlled Target</div>\n * @code\n * <button aria-expanded=\"true\" aria-controls=\"target-aria-hidden\">Expanded:</button>\n * <div id=\"target-aria-hidden\" aria-hidden=\"false\">Controlled Target</div>\n * <hr>\n * <button aria-expanded=\"true\" aria-controls=\"target-hidden\">Expanded:</button>\n * <div id=\"target-hidden\">Controlled Target</div>\n */\n\n/**\n * You can add animations/transitions on the controlled element by adding the `data-animate` attribute with the animation name.\n * The animation name will be used to add the necessary classes to the element to trigger the animation.\n * Please refer to the animate function for more information, what classes will be added and when.\n *\n * @location functions.expand.with-animation Expand with animation\n * @order 20\n * @example\n * <style>\n * .fade-enter-active,\n * .fade-leave-active {\n * transition: opacity 0.5s ease;\n * }\n *\n * .fade-enter-from,\n * .fade-leave-to {\n * opacity: 0;\n * }\n * </style>\n * <button aria-expanded=\"true\" aria-controls=\"target-hidden\">Toggle Controlled Area</button>\n * <div id=\"target-hidden\" data-animate=\"fade\">Controlled Target</div>\n */\nfunction toggleControlTarget(selector: string, show: boolean, callback: () => void): void {\n const target = document.querySelector<HTMLElement>(selector)\n\n if (!target) {\n return\n }\n\n const animationName = target.getAttribute('data-animate')\n const toggleHide = (): void => {\n if (target.hasAttribute('aria-hidden')) {\n target.setAttribute('aria-hidden', show ? 'false' : 'true')\n } else if (show) {\n target.removeAttribute('hidden')\n } else {\n target.setAttribute('hidden', '')\n }\n\n callback()\n }\n\n if (show) {\n // set tabindex=0 for all elements with tabindex=-1 that are not inside an aria-hidden element\n target\n .querySelectorAll<HTMLElement>(\n ':scope > [tabindex=\"-1\"], [tabindex=\"-1\"]:not([aria-hidden=\"true\"] [tabindex=\"-1\"], [hidden] [tabindex=\"-1\"])',\n )\n .forEach(el => {\n el.setAttribute('tabindex', '0')\n })\n } else {\n // set tabindex=-1 for all elements with tabindex=0\n target.querySelectorAll<HTMLElement>('[tabindex=\"0\"]').forEach(el => {\n el.setAttribute('tabindex', '-1')\n })\n }\n\n toggleInert(target, show)\n\n if (animationName !== null && animationName !== '') {\n if (show) {\n toggleHide()\n animate(target, animationName, show)\n } else {\n animate(target, animationName, show, toggleHide)\n }\n } else {\n toggleHide()\n }\n}\n\n/**\n * Initialize expandable/collapsable elements by using the\n * [aria-expanded](https://developer.mozilla.org/en-US/docs/Web/Accessibility/ARIA/Attributes/aria-expanded) attribute.\n *\n * When an element with the `aria-expanded` attribute is clicked, the value of the attribute will\n * be toggled between `true` and `false`.\n *\n * @location functions.expand Expand\n * @example\n * <style>\n * button::after {\n * content: ' ' attr(aria-expanded);\n * }\n * </style>\n * <button aria-expanded=\"false\">Expanded:</button>\n * @code\n * <button aria-expanded=\"false\">Expanded:</button>\n */\nexport function initExpand(): void {\n document.querySelectorAll<HTMLElement>('[aria-expanded]').forEach(expander => {\n const controlTarget = expander.getAttribute('aria-controls')\n const toggle = (e: MouseEvent): void => {\n const expanded = expander.getAttribute('aria-expanded') === 'true'\n const toggleExpanded = (): void => {\n expander.setAttribute('aria-expanded', expanded ? 'false' : 'true') // when expanded we need to set false\n }\n\n // if data-hide-same-level is set, we need to klick all other expanded elements to close them\n if (expander.parentElement && expander.hasAttribute('data-hide-same-level')) {\n Array.from(expander.parentElement.querySelectorAll(':scope > [aria-expanded=\"true\"]'))\n .filter(el => el !== expander && el !== e.relatedTarget)\n .forEach(sibling => {\n sibling.dispatchEvent(\n new MouseEvent('click', { bubbles: true, relatedTarget: expander }),\n )\n })\n }\n\n if (controlTarget !== null && controlTarget !== '') {\n toggleControlTarget(`#${controlTarget}`, !expanded, toggleExpanded)\n } else {\n toggleExpanded()\n }\n }\n\n expander.addEventListener('click', toggle)\n\n if (controlTarget !== null && controlTarget !== '') {\n // select all controls inside the controlled area that have the same aria-controls attribute\n document\n .querySelectorAll<HTMLElement>(`#${controlTarget} [aria-controls=\"${controlTarget}\"]`)\n .forEach(control => {\n control.addEventListener('click', toggle)\n })\n }\n })\n}\n","function createSidebar(sidebar: HTMLElement): void {\n const links: Record<string, HTMLLinkElement> = {}\n const observer = new IntersectionObserver(\n entries => {\n const activeEntries = entries.filter(entry => entry.isIntersecting)\n\n if (activeEntries.length <= 0) {\n return\n }\n\n Object.keys(links).forEach(id => {\n links[id].classList.remove('active')\n })\n\n const activeLink = links[activeEntries[0].target.id]\n\n activeLink.classList.add('active')\n if (activeLink?.parentElement?.parentElement?.parentElement instanceof HTMLLIElement) {\n activeLink.parentElement.parentElement.parentElement\n .querySelector('a')\n ?.classList\n .add('active')\n }\n },\n {\n root: null,\n rootMargin: '0px 0px -90% 0px',\n threshold: 0.5,\n },\n )\n\n sidebar.querySelectorAll<HTMLLinkElement>('a[href^=\"#\"]').forEach(link => {\n const id = link.href.split('#')[1]\n const target = document.getElementById(id)\n\n if (target) {\n observer.observe(target)\n links[id] = link\n }\n })\n}\n\nexport function initSidebar(): void {\n document.querySelectorAll('[data-sidebar]').forEach(sidebar => {\n createSidebar(sidebar as HTMLElement)\n })\n}\n","import { initExample } from './services/example'\nimport { initExpand } from './services/expand'\nimport { initSidebar } from './services/sidebar'\nimport { ready } from './utils/dom'\n\nready(() => {\n initExpand()\n initExample()\n initSidebar()\n})\n"],"names":[],"mappings":"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"}