@blockquote-web-components/blockquote-controller-context-meta 1.0.4 → 1.1.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -1,102 +1,34 @@
1
- ![Lit](https://img.shields.io/badge/lit-3.0.0-blue.svg)
2
-
3
- `BlockquoteControllerContextMeta` is a Lit Reactive Controller that encapsulates the controllers provided by @lit/context.
4
-
5
- **Features:**
6
- - It enables a component to serve as both a provider and a consumer.
7
- - It places the consumer after the first update to reduce the chance of a consumer in LightDOM requesting a context that currently lacks a provider.
8
- - Create a context object using a global symbol (Symbol.for('my-context')).
9
-
10
- <hr>
11
-
12
- ### Demo
13
-
14
- [![Open in StackBlitz](https://developer.stackblitz.com/img/open_in_stackblitz.svg)](https://stackblitz.com/github/oscarmarina/blockquote-web-components/tree/main/packages/controllers/blockquote-controller-context-meta)
15
-
16
- ### Usage
17
- - [Lit examples context-basics](https://lit.dev/playground/#sample=examples/context-basics)
18
- ```js
19
-
20
- import { html, LitElement, css } from 'lit';
21
- import { BlockquoteControllerContextMeta } from '@blockquote-web-components/blockquote-controller-context-meta';
22
-
23
- export class ProviderEl extends LitElement {
24
- static styles = css`
25
- slot {
26
- display: block;
27
- border: dashed 4px grey;
28
- padding: 0px 10px;
29
- }
30
-
31
- :host {
32
- display: block;
33
- border: solid 4px gainsboro;
34
- padding: 2px;
35
- }
36
-
37
- h3 {
38
- margin-top: 0;
39
- }
40
- `;
1
+ ### `src/BaseContextMetaElement.js`:
41
2
 
42
- static properties = {
43
- data: {},
44
- };
3
+ #### class: `BaseContextMetaElement`
45
4
 
46
- constructor() {
47
- super();
48
- this._provider = new BlockquoteControllerContextMeta(this, {
49
- context: 'contextKey', // String used as key in Symbol.for when creating context with createContext(Symbol.for(context))
50
- });
5
+ ##### Methods
51
6
 
52
- this.data = 'Initial';
53
- }
7
+ | Name | Privacy | Description | Parameters | Return | Inherited From |
8
+ | -------------------------- | ------- | ------------------------------------------------------------ | ------------------------------------ | --------------------------------- | -------------- |
9
+ | `initOrGetContextProvider` | | Initializes or returns the existing context meta controller. | `contextOrOptions: string \| Object` | `BlockquoteControllerContextMeta` | |
54
10
 
55
- // `data` will be provided to any consumer that is in the DOM tree below it.
56
- set data(value) {
57
- this._data = value;
58
- this._provider.setValue(value);
59
- }
11
+ <details><summary>Private API</summary>
60
12
 
61
- get data() {
62
- return this._data;
63
- }
13
+ ##### Fields
64
14
 
65
- render() {
66
- return html`
67
- <h3>Provider's data: <code>${this.data}</code></h3>
68
- <slot></slot>
69
- `;
70
- }
71
- }
72
- customElements.define('provider-el', ProviderEl);
15
+ | Name | Privacy | Type | Default | Description | Inherited From |
16
+ | ---------------------------- | ------- | ---------------------------------------------- | ----------- | --------------------------------------- | -------------- |
17
+ | `#controllerBaseContextMeta` | private | `BlockquoteControllerContextMeta \| undefined` | `undefined` | Stores the context controller instance. | |
73
18
 
74
- export class ConsumerEl extends LitElement {
75
- _consumer = new BlockquoteControllerContextMeta(this, {
76
- context: 'contextKey', // String used as key in Symbol.for when creating context with createContext(Symbol.for(context))
77
- callback: (v) => {
78
- this.setAttribute('data-callback', v);
79
- },
80
- });
19
+ </details>
81
20
 
21
+ <hr/>
82
22
 
83
- // `providedData` will be populated by the first ancestor element which
84
- // provides a value for `context`.
23
+ #### Exports
85
24
 
86
- get providedData() {
87
- return this._consumer.value;
88
- }
25
+ | Kind | Name | Declaration | Module | Package |
26
+ | ---- | ------------------------ | ---------------------- | ----------------------------- | ------- |
27
+ | `js` | `BaseContextMetaElement` | BaseContextMetaElement | src/BaseContextMetaElement.js | |
89
28
 
90
- render() {
91
- return html`<h3>Consumer data: <code>${this.providedData}</code></h3>
92
- <hr />
93
- <slot></slot>`;
94
- }
95
- }
96
- customElements.define('consumer-el', ConsumerEl);
97
- ```
29
+ ![Lit](https://img.shields.io/badge/lit-3.0.0-blue.svg)
98
30
 
99
- <hr>
31
+ `BlockquoteControllerContextMeta` is a Lit Reactive Controller that encapsulates the controllers provided by
100
32
 
101
33
 
102
34
  ### `src/BlockquoteControllerContextMeta.js`:
@@ -105,14 +37,14 @@ customElements.define('consumer-el', ConsumerEl);
105
37
 
106
38
  ##### Fields
107
39
 
108
- | Name | Privacy | Type | Default | Description | Inherited From |
109
- | ---------------------- | ------- | ---- | ---------------------------------------------------------------------------------------------------------- | ----------- | -------------- |
110
- | `value` | | | | | |
111
- | `context` | | | | | |
112
- | `initialValue` | | | `initialValue` | | |
113
- | `callback` | | | `callback` | | |
114
- | `host` | | | `host` | | |
115
- | `_contextMetaProvider` | | | `new ContextProvider(this.host, { context: this.context, initialValue: this.initialValue, })` | | |
40
+ | Name | Privacy | Type | Default | Description | Inherited From |
41
+ | ---------------------- | ------- | ---- | --------------------------------------------------------------------------------------------- | ----------- | -------------- |
42
+ | `value` | | | | | |
43
+ | `context` | | | | | |
44
+ | `initialValue` | | | `initialValue` | | |
45
+ | `callback` | | | `callback` | | |
46
+ | `host` | | | `host` | | |
47
+ | `_contextMetaProvider` | | | `new ContextProvider(this.host, { context: this.context, initialValue: this.initialValue, })` | | |
116
48
 
117
49
  ##### Methods
118
50
 
@@ -123,11 +55,20 @@ customElements.define('consumer-el', ConsumerEl);
123
55
 
124
56
  <hr/>
125
57
 
58
+ #### Variables
59
+
60
+ | Name | Description | Type |
61
+ | ------------------- | ----------- | -------- |
62
+ | `contextMetaSymbol` | | `string` |
63
+
64
+ <hr/>
65
+
126
66
  #### Exports
127
67
 
128
- | Kind | Name | Declaration | Module | Package |
129
- | ---- | --------------------------------- | ----------- | -------------------------------------- | ------- |
130
- | `js` | `BlockquoteControllerContextMeta` | ContextMeta | src/BlockquoteControllerContextMeta.js | |
68
+ | Kind | Name | Declaration | Module | Package |
69
+ | ---- | --------------------------------- | ----------------- | -------------------------------------- | ------- |
70
+ | `js` | `contextMetaSymbol` | contextMetaSymbol | src/BlockquoteControllerContextMeta.js | |
71
+ | `js` | `BlockquoteControllerContextMeta` | ContextMeta | src/BlockquoteControllerContextMeta.js | |
131
72
 
132
73
  ### `src/index.js`:
133
74
 
@@ -136,3 +77,108 @@ customElements.define('consumer-el', ConsumerEl);
136
77
  | Kind | Name | Declaration | Module | Package |
137
78
  | ---- | --------------------------------- | ------------------------------- | ------------------------------------ | ------- |
138
79
  | `js` | `BlockquoteControllerContextMeta` | BlockquoteControllerContextMeta | ./BlockquoteControllerContextMeta.js | |
80
+ | `js` | `BaseContextMetaElement` | BaseContextMetaElement | ./BaseContextMetaElement.js | |
81
+
82
+ <hr>
83
+
84
+ ### `src/BaseContextMetaElement.js`:
85
+ `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.
86
+ 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)**
87
+ > [Is it possible to make normal dom elements context providers?](https://github.com/lit/lit/discussions/4690)
88
+
89
+ <hr>
90
+
91
+ ### Demo
92
+
93
+ [![Open in StackBlitz](https://developer.stackblitz.com/img/open_in_stackblitz.svg)](https://stackblitz.com/github/oscarmarina/flow-element)
94
+
95
+ ### Features
96
+ It incorporates functionality to handle context consumption and presentation as a standard block element.
97
+
98
+ 1. The `:host` CSS rules ensure the element behaves like a block-level element and respects the `hidden` attribute to hide itself.
99
+ ```js
100
+ static styles = [
101
+ css`
102
+ :host {
103
+ display: block;
104
+ }
105
+ :host([hidden]),
106
+ [hidden] {
107
+ display: none !important;
108
+ }
109
+ `,
110
+ ];
111
+ ```
112
+
113
+ 2. The initOrGetContextProvider method allows setting up a context consumer on the element. It creates a new BlockquoteControllerContextMeta if one does not already exist.
114
+ ```js
115
+ initOrGetContextProvider(contextOrOptions = contextMetaSymbol) {
116
+ const ctx =
117
+ contextOrOptions?.context !== undefined
118
+ ? { ...contextOrOptions }
119
+ : { context: contextOrOptions };
120
+
121
+ if (!this.#controllerBaseContextMeta) {
122
+ this.#controllerBaseContextMeta = new BlockquoteControllerContextMeta(this, ctx);
123
+ }
124
+ return this.#controllerBaseContextMeta;
125
+ }
126
+ ```
127
+
128
+ 3. Set a default role of 'presentation' to ensure it behaves semantically like a non-interactive container.
129
+ ```js
130
+ connectedCallback() {
131
+ super.connectedCallback?.();
132
+ Object.assign(this, { role: this.role ?? 'presentation' });
133
+ }
134
+ ```
135
+
136
+ 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).
137
+ ```js
138
+ render() {
139
+ return html`<slot></slot>`;
140
+ }
141
+ ```
142
+
143
+
144
+ ### Usage Example: FlownElement
145
+ To demonstrate the utility of BaseContextMetaElement, let's create a derived class called FlownElement:
146
+
147
+ 1. Define Properties: The surface property is declared with reflection, allowing it to influence rendering and context behavior dynamically.
148
+ ```js
149
+ static properties = {
150
+ surface: { reflect: true },
151
+ };
152
+ ```
153
+
154
+ 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.
155
+ ```js
156
+ constructor() {
157
+ super();
158
+ this.surface = undefined;
159
+ this.flowController = this.initOrGetContextProvider(consumerContext);
160
+ }
161
+ ```
162
+
163
+ 3. Update Context Values: The willUpdate lifecycle method updates the context value whenever the surface property changes, ensuring context-sensitive operations react appropriately.
164
+ ```js
165
+ willUpdate(props) {
166
+ super.willUpdate?.(props);
167
+ if (props.has('surface')) {
168
+ this.flowController?.setValue(this.surface);
169
+ }
170
+ }
171
+ ```
172
+
173
+
174
+ ### Usage Example:
175
+ Here's how you might use the FlownElement in your HTML:
176
+
177
+ ```html
178
+ <flow-element surface="dim">
179
+ <!-- Child content that can consume context from this provider -->
180
+ </flow-element>
181
+ ```
182
+
183
+ 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.
184
+
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@blockquote-web-components/blockquote-controller-context-meta",
3
- "version": "1.0.4",
3
+ "version": "1.1.1",
4
4
  "description": "Webcomponent blockquote-controller-context-meta following open-wc recommendations",
5
5
  "keywords": [
6
6
  "lit",
@@ -103,5 +103,5 @@
103
103
  "access": "public"
104
104
  },
105
105
  "customElements": "custom-elements.json",
106
- "gitHead": "015e61740035c23471a5164f460ce03b05adab32"
106
+ "gitHead": "a425e9d97b373a9e13b86d5b71f9a3799205f41e"
107
107
  }
@@ -0,0 +1,153 @@
1
+ import { LitElement, html, css } from 'lit';
2
+ import {
3
+ BlockquoteControllerContextMeta,
4
+ contextMetaSymbol,
5
+ } from './BlockquoteControllerContextMeta.js';
6
+ /**
7
+ * `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.
8
+ * 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)**
9
+ * > [Is it possible to make normal dom elements context providers?](https://github.com/lit/lit/discussions/4690)
10
+ *
11
+ * <hr>
12
+ *
13
+ * ### Demo
14
+ *
15
+ * [![Open in StackBlitz](https://developer.stackblitz.com/img/open_in_stackblitz.svg)](https://stackblitz.com/github/oscarmarina/flow-element)
16
+ *
17
+ * ### Features
18
+ * It incorporates functionality to handle context consumption and presentation as a standard block element.
19
+ *
20
+ * 1. The `:host` CSS rules ensure the element behaves like a block-level element and respects the `hidden` attribute to hide itself.
21
+ * ```js
22
+ * static styles = [
23
+ * css`
24
+ * :host {
25
+ * display: block;
26
+ * }
27
+ * :host([hidden]),
28
+ * [hidden] {
29
+ * display: none !important;
30
+ * }
31
+ * `,
32
+ * ];
33
+ * ```
34
+ *
35
+ * 2. The initOrGetContextProvider method allows setting up a context consumer on the element. It creates a new BlockquoteControllerContextMeta if one does not already exist.
36
+ * ```js
37
+ * initOrGetContextProvider(contextOrOptions = contextMetaSymbol) {
38
+ * const ctx =
39
+ * contextOrOptions?.context !== undefined
40
+ * ? { ...contextOrOptions }
41
+ * : { context: contextOrOptions };
42
+ *
43
+ * if (!this.#controllerBaseContextMeta) {
44
+ * this.#controllerBaseContextMeta = new BlockquoteControllerContextMeta(this, ctx);
45
+ * }
46
+ * return this.#controllerBaseContextMeta;
47
+ * }
48
+ * ```
49
+ *
50
+ * 3. Set a default role of 'presentation' to ensure it behaves semantically like a non-interactive container.
51
+ * ```js
52
+ * connectedCallback() {
53
+ * super.connectedCallback?.();
54
+ * Object.assign(this, { role: this.role ?? 'presentation' });
55
+ * }
56
+ * ```
57
+ *
58
+ * 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).
59
+ * ```js
60
+ * render() {
61
+ * return html`<slot></slot>`;
62
+ * }
63
+ * ```
64
+ *
65
+ *
66
+ * ### Usage Example: FlownElement
67
+ * To demonstrate the utility of BaseContextMetaElement, let's create a derived class called FlownElement:
68
+ *
69
+ * 1. Define Properties: The surface property is declared with reflection, allowing it to influence rendering and context behavior dynamically.
70
+ * ```js
71
+ * static properties = {
72
+ * surface: { reflect: true },
73
+ * };
74
+ * ```
75
+ *
76
+ * 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.
77
+ * ```js
78
+ * constructor() {
79
+ * super();
80
+ * this.surface = undefined;
81
+ * this.flowController = this.initOrGetContextProvider(consumerContext);
82
+ * }
83
+ * ```
84
+ *
85
+ * 3. Update Context Values: The willUpdate lifecycle method updates the context value whenever the surface property changes, ensuring context-sensitive operations react appropriately.
86
+ * ```js
87
+ * willUpdate(props) {
88
+ * super.willUpdate?.(props);
89
+ * if (props.has('surface')) {
90
+ * this.flowController?.setValue(this.surface);
91
+ * }
92
+ * }
93
+ * ```
94
+ *
95
+ *
96
+ * ### Usage Example:
97
+ * Here's how you might use the FlownElement in your HTML:
98
+ *
99
+ * ```html
100
+ * <flow-element surface="dim">
101
+ * <!-- Child content that can consume context from this provider -->
102
+ * </flow-element>
103
+ * ```
104
+ *
105
+ * 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.
106
+ */
107
+ export class BaseContextMetaElement extends LitElement {
108
+ /**
109
+ * Stores the context controller instance.
110
+ * @type {BlockquoteControllerContextMeta | undefined}
111
+ */
112
+ #controllerBaseContextMeta = undefined;
113
+
114
+ static styles = [
115
+ css`
116
+ :host {
117
+ display: block;
118
+ }
119
+ :host([hidden]),
120
+ [hidden] {
121
+ display: none !important;
122
+ }
123
+ `,
124
+ ];
125
+
126
+ /**
127
+ * Initializes or returns the existing context meta controller.
128
+ * @param {string | Object} [contextOrOptions=contextMetaSymbol] - context name.
129
+ * @returns {BlockquoteControllerContextMeta} The instance of the context meta.
130
+ */
131
+ initOrGetContextProvider(contextOrOptions = contextMetaSymbol) {
132
+ const ctx =
133
+ contextOrOptions?.context !== undefined
134
+ ? { ...contextOrOptions }
135
+ : { context: contextOrOptions };
136
+
137
+ if (!this.#controllerBaseContextMeta) {
138
+ this.#controllerBaseContextMeta = new BlockquoteControllerContextMeta(this, ctx);
139
+ }
140
+ return this.#controllerBaseContextMeta;
141
+ }
142
+
143
+ connectedCallback() {
144
+ super.connectedCallback?.();
145
+ Object.assign(this, { role: this.role ?? 'presentation' });
146
+ }
147
+
148
+ render() {
149
+ return html`
150
+ <slot></slot>
151
+ `;
152
+ }
153
+ }
@@ -1,5 +1,6 @@
1
1
  import { ReactiveController, ReactiveControllerHost } from 'lit';
2
2
  import { Context, ContextType } from '@lit/context';
3
+ export declare const contextMetaSymbol = 'context-meta-symbol';
3
4
 
4
5
  declare class ContextMeta<
5
6
  TMeta extends Context<unknown, unknown>,
@@ -7,7 +8,7 @@ declare class ContextMeta<
7
8
  > implements ReactiveController
8
9
  {
9
10
  private host;
10
- private context;
11
+ private context?;
11
12
  private initialValue?;
12
13
  private callback?;
13
14
  private _contextMetaProvider;
@@ -19,7 +20,7 @@ declare class ContextMeta<
19
20
  initialValue,
20
21
  callback,
21
22
  }: {
22
- context: string;
23
+ context?: string;
23
24
  initialValue?: ContextType<TMeta>;
24
25
  callback?: (v: ContextType<TMeta>, dispose?: () => void) => void;
25
26
  },
@@ -1,5 +1,6 @@
1
1
  import { createContext, ContextProvider, ContextConsumer } from '@lit/context';
2
2
 
3
+ export const contextMetaSymbol = 'context-meta-symbol';
3
4
  /**
4
5
  * ![Lit](https://img.shields.io/badge/lit-3.0.0-blue.svg)
5
6
  *
@@ -105,12 +106,12 @@ class ContextMeta {
105
106
  /**
106
107
  * @param {import('lit').ReactiveElement} host - The host object.
107
108
  * @param {{
108
- * context: string,
109
+ * context?: string,
109
110
  * initialValue?: import('@lit/context').ContextType<*>,
110
111
  * callback?: (value: import('@lit/context').ContextType<*>, dispose?: () => void) => void
111
112
  * }} arg - The arguments for the constructor.
112
113
  */
113
- constructor(host, { context, initialValue, callback }) {
114
+ constructor(host, { context = contextMetaSymbol, initialValue, callback }) {
114
115
  this.context = createContext(Symbol.for(context));
115
116
  this.initialValue = initialValue;
116
117
  this.callback = callback;
package/src/index.js CHANGED
@@ -1 +1,2 @@
1
1
  export { BlockquoteControllerContextMeta } from './BlockquoteControllerContextMeta.js';
2
+ export { BaseContextMetaElement } from './BaseContextMetaElement.js';