@blockquote-web-components/blockquote-controller-context-meta 1.2.7 → 1.3.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.
package/README.md CHANGED
@@ -1,133 +1,45 @@
1
1
  ![Lit](https://img.shields.io/badge/lit-3.0.0-blue.svg)
2
2
 
3
- `BaseContextMetaElement` is inspired by the concept of 'Customized Built-in Elements', focusing on extending native HTML elements like `div` using Lit's features and the Context API.
4
- This approach simplifies the integration of context providers into a standard elements, enhancing functionality while preserving the core behavior of standard elements. **[All Structural Roles and Their HTML Equivalents](https://www.w3.org/WAI/ARIA/apg/practices/structural-roles/#allstructuralrolesandtheirhtmlequivalents)**
5
- > [Is it possible to make normal dom elements context providers?](https://github.com/lit/lit/discussions/4690)
3
+ `BaseContextMetaElement` simulates the behavior of a `div` using ARIA roles,
4
+ preserving standard HTML behaviors while enhancing functionality.
6
5
 
7
- <hr>
8
-
9
- ### Demo
6
+ ## Demo
10
7
 
11
8
  [![Open in StackBlitz](https://developer.stackblitz.com/img/open_in_stackblitz.svg)](https://stackblitz.com/github/oscarmarina/flow-element)
12
9
 
13
- ### Features
14
- It incorporates functionality to handle context consumption and presentation as a standard block element.
15
-
16
- 1. The `:host` CSS rules ensure the element behaves like a block-level element and respects the `hidden` attribute to hide itself.
17
- ```js
18
- static styles = [
19
- css`
20
- :host {
21
- display: block;
22
- }
23
- :host([hidden]),
24
- [hidden] {
25
- display: none !important;
26
- }
27
- `,
28
- ];
29
- ```
30
-
31
- 2. The initOrGetContextProvider method allows setting up a context consumer on the element. It creates a new BlockquoteControllerContextMeta if one does not already exist.
32
- ```js
33
- initOrGetContextProvider(contextOrOptions = contextMetaSymbol) {
34
- const ctx =
35
- contextOrOptions?.context !== undefined
36
- ? { ...contextOrOptions }
37
- : { context: contextOrOptions };
38
-
39
- if (!this.#controllerBaseContextMeta) {
40
- this.#controllerBaseContextMeta = new BlockquoteControllerContextMeta(this, ctx);
41
- }
42
- return this.#controllerBaseContextMeta;
43
- }
44
- ```
45
-
46
- 3. Set a default role of 'presentation' to ensure it behaves semantically like a non-interactive container.
47
- ```js
48
- connectedCallback() {
49
- super.connectedCallback?.();
50
- Object.assign(this, { role: this.role ?? 'presentation' });
51
- }
52
- ```
53
-
54
- 4. The render method includes a <slot>, which allows this element to be a flexible container for any child content, mimicking the behavior of a [flow element](https://developer.mozilla.org/en-US/docs/Web/HTML/Content_categories#flow_content).
55
- ```js
56
- render() {
57
- return html`<slot></slot>`;
58
- }
59
- ```
60
-
61
-
62
- ### Usage Example: FlownElement
63
- To demonstrate the utility of BaseContextMetaElement, let's create a derived class called FlownElement:
64
-
65
- 1. Define Properties: The surface property is declared with reflection, allowing it to influence rendering and context behavior dynamically.
66
- ```js
67
- static properties = {
68
- surface: { reflect: true },
69
- };
70
- ```
71
-
72
- 2. Set Context on Construction: The constructor calls initOrGetContextProvider with a specific context, enabling the element to participate in the context API from its inception.
73
- ```js
74
- constructor() {
75
- super();
76
- this.surface = undefined;
77
- this.flowController = this.initOrGetContextProvider(consumerContext);
78
- }
79
- ```
80
-
81
- 3. Update Context Values: The willUpdate lifecycle method updates the context value whenever the surface property changes, ensuring context-sensitive operations react appropriately.
82
- ```js
83
- willUpdate(props) {
84
- super.willUpdate?.(props);
85
- if (props.has('surface')) {
86
- this.flowController?.setValue(this.surface);
87
- }
88
- }
89
- ```
90
-
91
-
92
- ### Usage Example:
93
- Here's how you might use the FlownElement in your HTML:
94
-
95
- ```html
96
- <flow-element surface="dim">
97
- <!-- Child content that can consume context from this provider -->
98
- </flow-element>
99
- ```
10
+ ## Features
11
+ - Acts as a structural element that follows HTML flow content rules.
12
+ - Provides a default ARIA role (`none`) to avoid unintended semantics.
13
+ - Can be used as a wrapper for contextual metadata.
100
14
 
101
- With this setup, FlownElement behaves like a [flow element](https://developer.mozilla.org/en-US/docs/Web/HTML/Content_categories#flow_content) but provides the additional benefit of context management via Lit's context API, allowing you to seamlessly integrate context-sensitive behavior without altering the parent element hierarchy.
15
+ ## Accessibility
16
+ By default, `BaseContextMetaElement` [assigns the role="none"](https://github.com/w3c/aria/pull/2383),
17
+ ensuring that it does not introduce unintended semantics in assistive technologies.
18
+ This behavior can be overridden by explicitly setting a different role.
102
19
 
20
+ **Related:** [ARIA Structural Roles](https://www.w3.org/WAI/ARIA/apg/practices/structural-roles/#allstructuralrolesandtheirhtmlequivalents)
103
21
 
104
- ### `src/BaseContextMetaElement.js`:
22
+ > Inspired by the discussion: [Is it possible to make normal DOM elements context providers?](https://github.com/lit/lit/discussions/4690)
23
+ **See Also:** [contextmeta provider directive](https://github.com/oscarmarina/blockquote-web-components/tree/main/packages/controllers/blockquote-controller-context-meta/src/directives/context-meta-provider.js)
105
24
 
106
- #### class: `BaseContextMetaElement`
25
+ With this setup, `BaseContextMetaElement` behaves like a [flow element](https://developer.mozilla.org/en-US/docs/Web/HTML/Content_categories#flow_content).
107
26
 
108
- ##### Methods
109
27
 
110
- | Name | Privacy | Description | Parameters | Return | Inherited From |
111
- | -------------------------- | ------- | ------------------------------------------------------------ | ------------------------------------ | --------------------------------- | -------------- |
112
- | `initOrGetContextProvider` | | Initializes or returns the existing context meta controller. | `contextOrOptions: string \| Object` | `BlockquoteControllerContextMeta` | |
113
-
114
- <details><summary>Private API</summary>
28
+ <hr>
115
29
 
116
- ##### Fields
117
30
 
118
- | Name | Privacy | Type | Default | Description | Inherited From |
119
- | ---------------------------- | ------- | ---------------------------------------------- | ----------- | --------------------------------------- | -------------- |
120
- | `#controllerBaseContextMeta` | private | `BlockquoteControllerContextMeta \| undefined` | `undefined` | Stores the context controller instance. | |
31
+ ### `src/BaseContextMetaElement.js`:
121
32
 
122
- </details>
33
+ #### class: `BaseContextMetaElement`, `base-context-meta`
123
34
 
124
35
  <hr/>
125
36
 
126
37
  #### Exports
127
38
 
128
- | Kind | Name | Declaration | Module | Package |
129
- | ---- | ------------------------ | ---------------------- | ----------------------------- | ------- |
130
- | `js` | `BaseContextMetaElement` | BaseContextMetaElement | src/BaseContextMetaElement.js | |
39
+ | Kind | Name | Declaration | Module | Package |
40
+ | --------------------------- | ------------------------ | ---------------------- | ----------------------------- | ------- |
41
+ | `js` | `BaseContextMetaElement` | BaseContextMetaElement | src/BaseContextMetaElement.js | |
42
+ | `custom-element-definition` | `base-context-meta` | BaseContextMetaElement | src/BaseContextMetaElement.js | |
131
43
 
132
44
  ![Lit](https://img.shields.io/badge/lit-3.0.0-blue.svg)
133
45
 
@@ -177,7 +89,7 @@ export class ProviderEl extends LitElement {
177
89
  constructor() {
178
90
  super();
179
91
  this._provider = new BlockquoteControllerContextMeta(this, {
180
- context: 'contextKey', // String used as key in Symbol.for when creating context with createContext(Symbol.for(context))
92
+ context: Symbol.for('contextKey')
181
93
  });
182
94
 
183
95
  this.data = 'Initial';
@@ -204,7 +116,7 @@ customElements.define('provider-el', ProviderEl);
204
116
 
205
117
  export class ConsumerEl extends LitElement {
206
118
  _consumer = new BlockquoteControllerContextMeta(this, {
207
- context: 'contextKey', // String used as key in Symbol.for when creating context with createContext(Symbol.for(context))
119
+ context: Symbol.for('contextKey')
208
120
  callback: (v) => {
209
121
  this.setAttribute('data-callback', v);
210
122
  },
@@ -256,9 +168,9 @@ customElements.define('consumer-el', ConsumerEl);
256
168
 
257
169
  #### Variables
258
170
 
259
- | Name | Description | Type |
260
- | ------------------- | ----------- | -------- |
261
- | `contextMetaSymbol` | | `string` |
171
+ | Name | Description | Type |
172
+ | ------------------- | ----------- | ---- |
173
+ | `contextMetaSymbol` | | |
262
174
 
263
175
  <hr/>
264
176
 
@@ -273,7 +185,51 @@ customElements.define('consumer-el', ConsumerEl);
273
185
 
274
186
  #### Exports
275
187
 
276
- | Kind | Name | Declaration | Module | Package |
277
- | ---- | --------------------------------- | ------------------------------- | ------------------------------------ | ------- |
278
- | `js` | `BlockquoteControllerContextMeta` | BlockquoteControllerContextMeta | ./BlockquoteControllerContextMeta.js | |
279
- | `js` | `BaseContextMetaElement` | BaseContextMetaElement | ./BaseContextMetaElement.js | |
188
+ | Kind | Name | Declaration | Module | Package |
189
+ | ---- | --------------------------------- | ------------------------------- | ------------------------------------------- | ------- |
190
+ | `js` | `BlockquoteControllerContextMeta` | BlockquoteControllerContextMeta | ./BlockquoteControllerContextMeta.js | |
191
+ | `js` | `BaseContextMetaElement` | BaseContextMetaElement | ./BaseContextMetaElement.js | |
192
+ | `js` | `contextMetaProvider` | contextMetaProvider | ./directives/context-meta-provider.js | |
193
+ | `js` | `cacheContextMetaProvider` | cacheContextMetaProvider | ./directives/cache-context-meta-provider.js | |
194
+ | `js` | `contextMetaKeyProvider` | contextMetaKeyProvider | ./directives/cache-context-meta-provider.js | |
195
+
196
+ ### `src/directives/cache-context-meta-provider.js`:
197
+
198
+ #### Variables
199
+
200
+ | Name | Description | Type |
201
+ | ------------------------ | ----------- | ---- |
202
+ | `contextMetaKeyProvider` | | |
203
+
204
+ <hr/>
205
+
206
+ #### Functions
207
+
208
+ | Name | Description | Parameters | Return |
209
+ | -------------------------- | ----------- | --------------------------- | ------ |
210
+ | `cacheContextMetaProvider` | | `element, contextOrOptions` | |
211
+
212
+ <hr/>
213
+
214
+ #### Exports
215
+
216
+ | Kind | Name | Declaration | Module | Package |
217
+ | ---- | -------------------------- | ------------------------ | --------------------------------------------- | ------- |
218
+ | `js` | `contextMetaKeyProvider` | contextMetaKeyProvider | src/directives/cache-context-meta-provider.js | |
219
+ | `js` | `cacheContextMetaProvider` | cacheContextMetaProvider | src/directives/cache-context-meta-provider.js | |
220
+
221
+ ### `src/directives/context-meta-provider.js`:
222
+
223
+ #### Variables
224
+
225
+ | Name | Description | Type |
226
+ | --------------------- | ----------- | ---- |
227
+ | `contextMetaProvider` | | |
228
+
229
+ <hr/>
230
+
231
+ #### Exports
232
+
233
+ | Kind | Name | Declaration | Module | Package |
234
+ | ---- | --------------------- | ------------------- | --------------------------------------- | ------- |
235
+ | `js` | `contextMetaProvider` | contextMetaProvider | src/directives/context-meta-provider.js | |
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@blockquote-web-components/blockquote-controller-context-meta",
3
- "version": "1.2.7",
3
+ "version": "1.3.0",
4
4
  "description": "Webcomponent blockquote-controller-context-meta following open-wc recommendations",
5
5
  "keywords": [
6
6
  "lit",
@@ -20,6 +20,12 @@
20
20
  "./BlockquoteControllerContextMeta.js": {
21
21
  "default": "./src/BlockquoteControllerContextMeta.js"
22
22
  },
23
+ "./BaseContextMetaElement.js": {
24
+ "default": "./src/BaseContextMetaElement.js"
25
+ },
26
+ "./contextMetaProvider.js": {
27
+ "default": "./directives/context-meta-provider.js"
28
+ },
23
29
  "./index.js": {
24
30
  "default": "./src/index.js"
25
31
  }
@@ -35,30 +41,26 @@
35
41
  "dev:vite": "vite build",
36
42
  "format": "npm run format:eslint && npm run format:prettier && npm run format:stylelint",
37
43
  "format:eslint": "eslint . --fix",
38
- "format:prettier": "prettier \"**/*.{js,ts,json,html}\" --write --ignore-path .prettierignore",
39
- "format:stylelint": "stylelint \"**/*.{scss,css}\" --fix --allow-empty-input --ignore-path .prettierignore",
44
+ "format:prettier": "prettier \"**/*.{js,ts,css,scss,html,json}\" --write --ignore-path .prettierignore",
45
+ "format:stylelint": "stylelint \"{demo,src}/**/*.{js,ts,css,scss,html}\" --fix --ignore-path .prettierignore",
40
46
  "postinstall": "npm run sort:package",
41
- "lint": "npm run lint:eslint && npm run lint:prettier && npm run lint:stylelint",
42
- "lint:eslint": "eslint .",
43
- "lint:prettier": "prettier \"**/*.{js,ts,json,html}\" --check --ignore-path .prettierignore",
44
- "lint:stylelint": "stylelint \"**/*.{scss,css}\" --allow-empty-input --ignore-path .prettierignore",
45
- "prepare": "husky",
46
47
  "preview:vite": "vite preview",
47
48
  "sass:watch": "sass-style-template",
48
49
  "sort:package": "npx sort-package-json",
49
- "start": "concurrently -k -r \"npm:sass:watch\" \"npm:vite\"",
50
+ "start": "concurrently -k -r \"npm:vite\" \"npm:sass:watch\"",
50
51
  "test": "vitest --run --browser.headless",
51
52
  "test:watch": "vitest",
52
53
  "vite": "vite"
53
54
  },
54
55
  "lint-staged": {
55
56
  "**/*.{js,ts,html}": [
56
- "npm run format:eslint"
57
+ "npm run format"
57
58
  ],
58
- "**/*.{js,ts,json,html}": [
59
+ "**/*.json": [
59
60
  "npm run format:prettier"
60
61
  ],
61
62
  "**/*.{scss,css}": [
63
+ "npm run format:prettier",
62
64
  "npm run format:stylelint"
63
65
  ]
64
66
  },
@@ -73,32 +75,58 @@
73
75
  {
74
76
  "files": "*.{scss,css}",
75
77
  "options": {
76
- "printWidth": 280,
77
78
  "singleQuote": false
78
79
  }
80
+ },
81
+ {
82
+ "files": "*.json",
83
+ "options": {
84
+ "parser": "json-stringify"
85
+ }
79
86
  }
80
87
  ]
81
88
  },
82
89
  "stylelint": {
83
90
  "extends": "stylelint-config-standard-scss",
91
+ "allowEmptyInput": true,
84
92
  "rules": {
85
93
  "custom-property-pattern": null,
86
94
  "no-duplicate-selectors": null,
87
95
  "color-function-notation": null,
88
- "alpha-value-notation": null
89
- }
96
+ "alpha-value-notation": null,
97
+ "media-feature-name-no-unknown": null,
98
+ "comment-empty-line-before": null,
99
+ "declaration-empty-line-before": null,
100
+ "property-no-vendor-prefix": null,
101
+ "selector-attribute-quotes": null,
102
+ "value-no-vendor-prefix": null
103
+ },
104
+ "overrides": [
105
+ {
106
+ "files": [
107
+ "**/*.html"
108
+ ],
109
+ "customSyntax": "postcss-html"
110
+ },
111
+ {
112
+ "files": [
113
+ "**/*.{ts,js}"
114
+ ],
115
+ "customSyntax": "postcss-lit"
116
+ }
117
+ ]
90
118
  },
91
119
  "dependencies": {
92
120
  "@lit/context": "^1.1.3",
93
121
  "lit": "^3.2.1"
94
122
  },
95
123
  "devDependencies": {
96
- "@blockquote-web-components/blockquote-base-common-dev-dependencies": "^1.11.0",
97
- "@blockquote-web-components/blockquote-base-embedded-webview": "^1.12.7"
124
+ "@blockquote-web-components/blockquote-base-common-dev-dependencies": "^1.11.2",
125
+ "@blockquote-web-components/blockquote-base-embedded-webview": "^1.12.9"
98
126
  },
99
127
  "publishConfig": {
100
128
  "access": "public"
101
129
  },
102
130
  "customElements": "custom-elements.json",
103
- "gitHead": "05d5206fdfaaae4b506c43e35afb5de1394bc8e5"
131
+ "gitHead": "9a325725a904f541664565dd720f4bb6b2f0fa05"
104
132
  }
@@ -1,148 +1,51 @@
1
1
  import {LitElement, html, css} from 'lit';
2
- import {
3
- BlockquoteControllerContextMeta,
4
- contextMetaSymbol,
5
- } from './BlockquoteControllerContextMeta.js';
2
+
6
3
  /**
7
4
  * ![Lit](https://img.shields.io/badge/lit-3.0.0-blue.svg)
8
5
  *
9
- * `BaseContextMetaElement` is inspired by the concept of 'Customized Built-in Elements', focusing on extending native HTML elements like `div` using Lit's features and the Context API.
10
- * This approach simplifies the integration of context providers into a standard elements, enhancing functionality while preserving the core behavior of standard elements. **[All Structural Roles and Their HTML Equivalents](https://www.w3.org/WAI/ARIA/apg/practices/structural-roles/#allstructuralrolesandtheirhtmlequivalents)**
11
- * > [Is it possible to make normal dom elements context providers?](https://github.com/lit/lit/discussions/4690)
12
- *
13
- * <hr>
6
+ * `BaseContextMetaElement` simulates the behavior of a `div` using ARIA roles,
7
+ * preserving standard HTML behaviors while enhancing functionality.
14
8
  *
15
- * ### Demo
9
+ * ## Demo
16
10
  *
17
11
  * [![Open in StackBlitz](https://developer.stackblitz.com/img/open_in_stackblitz.svg)](https://stackblitz.com/github/oscarmarina/flow-element)
18
12
  *
19
- * ### Features
20
- * It incorporates functionality to handle context consumption and presentation as a standard block element.
21
- *
22
- * 1. The `:host` CSS rules ensure the element behaves like a block-level element and respects the `hidden` attribute to hide itself.
23
- * ```js
24
- * static styles = [
25
- * css`
26
- * :host {
27
- * display: block;
28
- * }
29
- * :host([hidden]),
30
- * [hidden] {
31
- * display: none !important;
32
- * }
33
- * `,
34
- * ];
35
- * ```
36
- *
37
- * 2. The initOrGetContextProvider method allows setting up a context consumer on the element. It creates a new BlockquoteControllerContextMeta if one does not already exist.
38
- * ```js
39
- * initOrGetContextProvider(contextOrOptions = contextMetaSymbol) {
40
- * const ctx =
41
- * contextOrOptions?.context !== undefined
42
- * ? { ...contextOrOptions }
43
- * : { context: contextOrOptions };
44
- *
45
- * if (!this.#controllerBaseContextMeta) {
46
- * this.#controllerBaseContextMeta = new BlockquoteControllerContextMeta(this, ctx);
47
- * }
48
- * return this.#controllerBaseContextMeta;
49
- * }
50
- * ```
51
- *
52
- * 3. Set a default role of 'presentation' to ensure it behaves semantically like a non-interactive container.
53
- * ```js
54
- * connectedCallback() {
55
- * super.connectedCallback?.();
56
- * Object.assign(this, { role: this.role ?? 'presentation' });
57
- * }
58
- * ```
59
- *
60
- * 4. The render method includes a <slot>, which allows this element to be a flexible container for any child content, mimicking the behavior of a [flow element](https://developer.mozilla.org/en-US/docs/Web/HTML/Content_categories#flow_content).
61
- * ```js
62
- * render() {
63
- * return html`<slot></slot>`;
64
- * }
65
- * ```
66
- *
67
- *
68
- * ### Usage Example: FlownElement
69
- * To demonstrate the utility of BaseContextMetaElement, let's create a derived class called FlownElement:
13
+ * ## Features
14
+ * - Acts as a structural element that follows HTML flow content rules.
15
+ * - Provides a default ARIA role (`none`) to avoid unintended semantics.
16
+ * - Can be used as a wrapper for contextual metadata.
70
17
  *
71
- * 1. Define Properties: The surface property is declared with reflection, allowing it to influence rendering and context behavior dynamically.
72
- * ```js
73
- * static properties = {
74
- * surface: { reflect: true },
75
- * };
76
- * ```
18
+ * ## Accessibility
19
+ * By default, `BaseContextMetaElement` [assigns the role="none"](https://github.com/w3c/aria/pull/2383),
20
+ * ensuring that it does not introduce unintended semantics in assistive technologies.
21
+ * This behavior can be overridden by explicitly setting a different role.
77
22
  *
78
- * 2. Set Context on Construction: The constructor calls initOrGetContextProvider with a specific context, enabling the element to participate in the context API from its inception.
79
- * ```js
80
- * constructor() {
81
- * super();
82
- * this.surface = undefined;
83
- * this.flowController = this.initOrGetContextProvider(consumerContext);
84
- * }
85
- * ```
23
+ * **Related:** [ARIA Structural Roles](https://www.w3.org/WAI/ARIA/apg/practices/structural-roles/#allstructuralrolesandtheirhtmlequivalents)
86
24
  *
87
- * 3. Update Context Values: The willUpdate lifecycle method updates the context value whenever the surface property changes, ensuring context-sensitive operations react appropriately.
88
- * ```js
89
- * willUpdate(props) {
90
- * super.willUpdate?.(props);
91
- * if (props.has('surface')) {
92
- * this.flowController?.setValue(this.surface);
93
- * }
94
- * }
95
- * ```
25
+ * > Inspired by the discussion: [Is it possible to make normal DOM elements context providers?](https://github.com/lit/lit/discussions/4690)
26
+ * **See Also:** [contextmeta provider directive](https://github.com/oscarmarina/blockquote-web-components/tree/main/packages/controllers/blockquote-controller-context-meta/src/directives/context-meta-provider.js)
96
27
  *
28
+ * With this setup, `BaseContextMetaElement` behaves like a [flow element](https://developer.mozilla.org/en-US/docs/Web/HTML/Content_categories#flow_content).
97
29
  *
98
- * ### Usage Example:
99
- * Here's how you might use the FlownElement in your HTML:
100
30
  *
101
- * ```html
102
- * <flow-element surface="dim">
103
- * <!-- Child content that can consume context from this provider -->
104
- * </flow-element>
105
- * ```
106
- *
107
- * With this setup, FlownElement behaves like a [flow element](https://developer.mozilla.org/en-US/docs/Web/HTML/Content_categories#flow_content) but provides the additional benefit of context management via Lit's context API, allowing you to seamlessly integrate context-sensitive behavior without altering the parent element hierarchy.
31
+ * <hr>
108
32
  */
109
33
  export class BaseContextMetaElement extends LitElement {
110
- /**
111
- * Stores the context controller instance.
112
- * @type {BlockquoteControllerContextMeta | undefined}
113
- */
114
- #controllerBaseContextMeta = undefined;
115
-
116
- static styles = [
117
- css`
118
- :host {
119
- display: block;
120
- }
121
- :host([hidden]),
122
- [hidden] {
123
- display: none !important;
124
- }
125
- `,
126
- ];
127
-
128
- /**
129
- * Initializes or returns the existing context meta controller.
130
- * @param {string | Object} [contextOrOptions=contextMetaSymbol] - context name.
131
- * @returns {BlockquoteControllerContextMeta} The instance of the context meta.
132
- */
133
- initOrGetContextProvider(contextOrOptions = contextMetaSymbol) {
134
- const ctx =
135
- contextOrOptions?.context !== undefined ? {...contextOrOptions} : {context: contextOrOptions};
136
-
137
- if (!this.#controllerBaseContextMeta) {
138
- this.#controllerBaseContextMeta = new BlockquoteControllerContextMeta(this, ctx);
34
+ static styles = css`
35
+ :host {
36
+ display: block;
139
37
  }
140
- return this.#controllerBaseContextMeta;
141
- }
38
+ :host([hidden]),
39
+ [hidden] {
40
+ display: none !important;
41
+ }
42
+ `;
142
43
 
143
44
  connectedCallback() {
144
45
  super.connectedCallback?.();
145
- Object.assign(this, {role: this.role ?? 'presentation'});
46
+ if (!this.hasAttribute('role')) {
47
+ this.setAttribute('role', 'none');
48
+ }
146
49
  }
147
50
 
148
51
  render() {
@@ -151,3 +54,5 @@ export class BaseContextMetaElement extends LitElement {
151
54
  `;
152
55
  }
153
56
  }
57
+
58
+ customElements.define('base-context-meta', BaseContextMetaElement);
@@ -20,7 +20,7 @@ declare class ContextMeta<
20
20
  initialValue,
21
21
  callback,
22
22
  }: {
23
- context?: string;
23
+ context?: unknown;
24
24
  initialValue?: ContextType<TMeta>;
25
25
  callback?: (v: ContextType<TMeta>, dispose?: () => void) => void;
26
26
  },
@@ -1,6 +1,6 @@
1
1
  import {createContext, ContextProvider, ContextConsumer} from '@lit/context';
2
2
 
3
- export const contextMetaSymbol = 'context-meta-symbol';
3
+ export const contextMetaSymbol = Symbol.for('context-meta-symbol');
4
4
  /**
5
5
  * ![Lit](https://img.shields.io/badge/lit-3.0.0-blue.svg)
6
6
  *
@@ -50,7 +50,7 @@ export const contextMetaSymbol = 'context-meta-symbol';
50
50
  * constructor() {
51
51
  * super();
52
52
  * this._provider = new BlockquoteControllerContextMeta(this, {
53
- * context: 'contextKey', // String used as key in Symbol.for when creating context with createContext(Symbol.for(context))
53
+ * context: Symbol.for('contextKey')
54
54
  * });
55
55
  *
56
56
  * this.data = 'Initial';
@@ -77,7 +77,7 @@ export const contextMetaSymbol = 'context-meta-symbol';
77
77
  *
78
78
  * export class ConsumerEl extends LitElement {
79
79
  * _consumer = new BlockquoteControllerContextMeta(this, {
80
- * context: 'contextKey', // String used as key in Symbol.for when creating context with createContext(Symbol.for(context))
80
+ * context: Symbol.for('contextKey')
81
81
  * callback: (v) => {
82
82
  * this.setAttribute('data-callback', v);
83
83
  * },
@@ -106,13 +106,13 @@ class ContextMeta {
106
106
  /**
107
107
  * @param {import('lit').ReactiveElement} host - The host object.
108
108
  * @param {{
109
- * context?: string,
109
+ * context?: *,
110
110
  * initialValue?: import('@lit/context').ContextType<*>,
111
111
  * callback?: (value: import('@lit/context').ContextType<*>, dispose?: () => void) => void
112
112
  * }} arg - The arguments for the constructor.
113
113
  */
114
114
  constructor(host, {context = contextMetaSymbol, initialValue, callback}) {
115
- this.context = createContext(Symbol.for(context));
115
+ this.context = createContext(context);
116
116
  this.initialValue = initialValue;
117
117
  this.callback = callback;
118
118
  this.host = host;
@@ -0,0 +1,15 @@
1
+ import {BlockquoteControllerContextMeta} from '../BlockquoteControllerContextMeta.js';
2
+
3
+ export const contextMetaKeyProvider = Symbol();
4
+
5
+ export const cacheContextMetaProvider = (element, contextOrOptions) => {
6
+ if (element[contextMetaKeyProvider]) {
7
+ return element[contextMetaKeyProvider];
8
+ }
9
+
10
+ const ctx =
11
+ contextOrOptions?.context !== undefined ? {...contextOrOptions} : {context: contextOrOptions};
12
+
13
+ element[contextMetaKeyProvider] = new BlockquoteControllerContextMeta(element, ctx);
14
+ return element[contextMetaKeyProvider];
15
+ };
@@ -0,0 +1,94 @@
1
+ import {Directive, directive, PartType} from 'lit/directive.js';
2
+ import {noChange} from 'lit';
3
+ import {cacheContextMetaProvider, contextMetaKeyProvider} from './cache-context-meta-provider.js';
4
+
5
+ /**
6
+ * `contextMetaProviderDirective` is a Lit directive that allows you to make normal DOM elements context providers.
7
+ * This directive can be used in both attribute and element bindings in Lit templates.
8
+ *
9
+ * > https://github.com/lit/lit/discussions/4690
10
+ *
11
+ * Usage:
12
+ * This directive converts a DOM element into a Lit context provider using the BlockquoteControllerContextMeta class, which is a
13
+ * Lit Reactive Controller that encapsulates the controllers provided by [@lit/context](https://lit.dev/docs/data/context/).
14
+ *
15
+ * ## Features
16
+ * - Allows non-Lit elements to provide context.
17
+ * - Works seamlessly with [`@lit/context`](https://lit.dev/docs/data/context/).
18
+ * - Utilizes `BlockquoteControllerContextMeta`, a Lit Reactive Controller for managing context.
19
+
20
+ *
21
+ * js```
22
+ * <div ${contextMetaProviderDirective(myContext, someValue)}>
23
+ * <!-- Children can consume the provided context -->
24
+ * </div>
25
+ * //
26
+ * <div data-info="${contextMetaProviderDirective(myContext, someValue)}"">
27
+ * <!-- Children can consume the provided context -->
28
+ * </div>
29
+ * ```;
30
+ */
31
+ class ContextMetaProviderDirective extends Directive {
32
+ /** @type {*} */
33
+ #partInfo = undefined;
34
+ #currentValue = undefined;
35
+
36
+ /**
37
+ * @param {import('lit/directive.js').PartInfo} partInfo - Information about the part this directive is bound to
38
+ */
39
+ constructor(partInfo) {
40
+ super(partInfo);
41
+ if (partInfo.type !== PartType.ATTRIBUTE && partInfo.type !== PartType.ELEMENT) {
42
+ throw new Error(
43
+ 'contextMetaProviderDirective can only be used in an attribute or element directive.'
44
+ );
45
+ }
46
+
47
+ this.#partInfo = partInfo;
48
+ }
49
+
50
+ /**
51
+ * Main render method called by Lit.
52
+ * @param {*} value - The context value to provide.
53
+ * @param {{
54
+ * context?: *,
55
+ * initialValue?: import('@lit/context').ContextType<*>,
56
+ * }} context - The context object.
57
+ * @returns {unknown} - The serialized context value or noChange.
58
+ */
59
+ render(value, context) {
60
+ if (value !== this.#currentValue) {
61
+ this.#currentValue = value;
62
+ this.updateValue(value, context);
63
+ return this.resolveAttrValue();
64
+ }
65
+ return noChange;
66
+ }
67
+
68
+ /**
69
+ * Updates the context value for the element.
70
+ * @param {*} value - The new context value.
71
+ * @param {{
72
+ * context?: *,
73
+ * initialValue?: import('@lit/context').ContextType<*>,
74
+ * }} context - The context object.
75
+ */
76
+ updateValue(value, context) {
77
+ const element = this.#partInfo.element;
78
+ cacheContextMetaProvider(element, context);
79
+ element[contextMetaKeyProvider].setValue(value);
80
+ }
81
+
82
+ /**
83
+ * Decides whether to return the currentValue if the directive is used as an attribute.
84
+ * @returns {unknown} - The serialized context value or noChange.
85
+ */
86
+ resolveAttrValue() {
87
+ if (this.#partInfo.type !== PartType.ATTRIBUTE) {
88
+ return noChange;
89
+ }
90
+ return this.#currentValue;
91
+ }
92
+ }
93
+
94
+ export const contextMetaProvider = directive(ContextMetaProviderDirective);
package/src/index.js CHANGED
@@ -1,2 +1,7 @@
1
1
  export {BlockquoteControllerContextMeta} from './BlockquoteControllerContextMeta.js';
2
2
  export {BaseContextMetaElement} from './BaseContextMetaElement.js';
3
+ export {contextMetaProvider} from './directives/context-meta-provider.js';
4
+ export {
5
+ cacheContextMetaProvider,
6
+ contextMetaKeyProvider,
7
+ } from './directives/cache-context-meta-provider.js';