@scalable.software/pin 0.2.0 → 0.2.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/LICENSE +144 -144
- package/README.md +365 -365
- package/dist/index.d.ts +3 -0
- package/dist/index.js +2 -0
- package/dist/{Pin.d.ts → pin.d.ts} +8 -13
- package/dist/{Pin.js → pin.js} +16 -23
- package/dist/{Pin.meta.d.ts → pin.meta.d.ts} +8 -13
- package/dist/{Pin.meta.js → pin.meta.js} +2 -2
- package/{src/Pin.style.css → dist/pin.style.css} +126 -122
- package/dist/{Pin.template.html → pin.template.html} +26 -12
- package/package.json +55 -56
- package/report/{Pin.report.json → pin.report.json} +668 -644
- package/src/index.ts +14 -0
- package/src/{Pin.meta.ts → pin.meta.ts} +108 -114
- package/{dist/Pin.style.css → src/pin.style.css} +126 -122
- package/src/{Pin.template.html → pin.template.html} +26 -12
- package/src/{Pin.ts → pin.ts} +318 -329
- package/dist/Index.d.ts +0 -4
- package/dist/Index.js +0 -2
- package/src/Index.ts +0 -25
package/README.md
CHANGED
|
@@ -1,365 +1,365 @@
|
|
|
1
|
-
# Pin Component Documentation
|
|
2
|
-
|
|
3
|
-
Below is a **comprehensive** document detailing the **Pin** component’s architecture, usage, and developer workflow. It prioritizes a **Quick Start** so you can see the pin in action right away, then dives into **State**, **Operations**, **Events**, and more advanced topics.
|
|
4
|
-
|
|
5
|
-
---
|
|
6
|
-
|
|
7
|
-
## 1. Introduction
|
|
8
|
-
|
|
9
|
-
The **Pin** component provides a toggleable element that can be pinned/unpinned and hidden/shown via both **imperative** and **declarative** APIs. It leverages custom Web Component features, including Shadow DOM, custom events, and attribute reflection for a clean, modular design.
|
|
10
|
-
|
|
11
|
-
### 1.1 Installation & Setup
|
|
12
|
-
|
|
13
|
-
1. **Clone the Repository**
|
|
14
|
-
|
|
15
|
-
```bash
|
|
16
|
-
git clone <repository-url>
|
|
17
|
-
cd pin-component
|
|
18
|
-
```
|
|
19
|
-
|
|
20
|
-
2. **Install Dependencies**
|
|
21
|
-
|
|
22
|
-
```bash
|
|
23
|
-
npm install
|
|
24
|
-
```
|
|
25
|
-
|
|
26
|
-
3. **Run Tests (Optional)**
|
|
27
|
-
|
|
28
|
-
```bash
|
|
29
|
-
npm test
|
|
30
|
-
```
|
|
31
|
-
|
|
32
|
-
- Ensures everything is working as expected before you start.
|
|
33
|
-
|
|
34
|
-
4. **Start Local Server**
|
|
35
|
-
```bash
|
|
36
|
-
npm run serve
|
|
37
|
-
```
|
|
38
|
-
- This runs a local development server, making `<pin-button>` available in your browser.
|
|
39
|
-
|
|
40
|
-
---
|
|
41
|
-
|
|
42
|
-
## 2. Quick Start Usage Walkthrough
|
|
43
|
-
|
|
44
|
-
This walkthrough demonstrates how to interact with `<pin-button>` right after installation, letting you see how the pin behaves before exploring its internal design.
|
|
45
|
-
|
|
46
|
-
1. **Open** the served page in your browser.
|
|
47
|
-
|
|
48
|
-
- You should see a `<pin-button>` component displayed.
|
|
49
|
-
|
|
50
|
-
2. **Open the Developer Tools**, select the **Console**.
|
|
51
|
-
|
|
52
|
-
3. **Get a reference** to the component:
|
|
53
|
-
|
|
54
|
-
```js
|
|
55
|
-
const pin = document.querySelector("pin-button");
|
|
56
|
-
```
|
|
57
|
-
|
|
58
|
-
4. **Create a handler** for when the pin is pinned:
|
|
59
|
-
|
|
60
|
-
```js
|
|
61
|
-
const onpin = (event) => {
|
|
62
|
-
console.log("Pin was pinned:", event.detail.status);
|
|
63
|
-
};
|
|
64
|
-
```
|
|
65
|
-
|
|
66
|
-
5. **Assign** that handler to the `onpin` property:
|
|
67
|
-
|
|
68
|
-
```js
|
|
69
|
-
pin.onpin = onpin;
|
|
70
|
-
```
|
|
71
|
-
|
|
72
|
-
6. **Pin** the component imperatively:
|
|
73
|
-
|
|
74
|
-
```js
|
|
75
|
-
pin.pin();
|
|
76
|
-
```
|
|
77
|
-
|
|
78
|
-
- This changes `status` from `unpinned` to `pinned`.
|
|
79
|
-
- Observe the console output: `"Pin was pinned: pinned"`.
|
|
80
|
-
|
|
81
|
-
7. **Inspect** the `<pin-button>` in the **Elements** tab:
|
|
82
|
-
|
|
83
|
-
```html
|
|
84
|
-
<pin-button status="pinned"></pin-button>
|
|
85
|
-
```
|
|
86
|
-
|
|
87
|
-
8. **Manually change** the `status` attribute to `"unpinned"`
|
|
88
|
-
|
|
89
|
-
- Notice the pin’s icon and internal state update.
|
|
90
|
-
|
|
91
|
-
9. **Check** the current status in the console:
|
|
92
|
-
|
|
93
|
-
```js
|
|
94
|
-
pin.status; // Should return "unpinned"
|
|
95
|
-
```
|
|
96
|
-
|
|
97
|
-
10. **Click** the `<pin-button>` in the UI
|
|
98
|
-
|
|
99
|
-
- By default, clicking toggles it between `pinned` and `unpinned`.
|
|
100
|
-
- If pinned, the `onpin` event is fired (if you have a listener).
|
|
101
|
-
|
|
102
|
-
11. **Check** the status again:
|
|
103
|
-
|
|
104
|
-
```js
|
|
105
|
-
pin.status; // "pinned" or "unpinned"
|
|
106
|
-
```
|
|
107
|
-
|
|
108
|
-
> **Visibility**
|
|
109
|
-
>
|
|
110
|
-
> - You can similarly call `pin.hide()` or `pin.show()` to toggle the `visible` state.
|
|
111
|
-
> - Watch for `onhide` or `onshow` events in the console.
|
|
112
|
-
|
|
113
|
-
For more details on **States**, **Operations**, and **Events**, consult the sections below or check the generated **API documentation** (see `npm run document` instructions).
|
|
114
|
-
|
|
115
|
-
---
|
|
116
|
-
|
|
117
|
-
## 3. Architectural Overview
|
|
118
|
-
|
|
119
|
-
### 3.1 Composition
|
|
120
|
-
|
|
121
|
-
- **Template** (e.g., `Pin.template.html`):
|
|
122
|
-
Defines DOM structure (a `.icon` container, pinned/unpinned SVGs, etc.).
|
|
123
|
-
|
|
124
|
-
- **Style** (e.g., `Pin.style.css`):
|
|
125
|
-
Encapsulates appearance, including hover effects, pinned/unpinned icon transitions.
|
|
126
|
-
|
|
127
|
-
- **Class** (`Pin.ts`):
|
|
128
|
-
Extends a base component class to handle lifecycle hooks, Shadow DOM creation, attribute reflection, etc.
|
|
129
|
-
|
|
130
|
-
> **Separation of Concerns**
|
|
131
|
-
>
|
|
132
|
-
> - **HTML** for structure
|
|
133
|
-
> - **CSS** for presentation
|
|
134
|
-
> - **TypeScript** for behavior
|
|
135
|
-
|
|
136
|
-
### 3.2 Class Lifecycle
|
|
137
|
-
|
|
138
|
-
Lifecycle methods are implemented in the base class and extended by the **Pin** component:
|
|
139
|
-
|
|
140
|
-
- **`connectedCallback()`**
|
|
141
|
-
|
|
142
|
-
1. Creates a Shadow DOM.
|
|
143
|
-
2. Clones the HTML template into the Shadow Root.
|
|
144
|
-
3. Inserts a `<link>` for scoped CSS.
|
|
145
|
-
4. Initializes default states (`visible`, `status`).
|
|
146
|
-
5. Sets up event listeners (e.g., on click).
|
|
147
|
-
|
|
148
|
-
- **`disconnectedCallback()`**
|
|
149
|
-
- Removes event listeners and cleans up references.
|
|
150
|
-
|
|
151
|
-
---
|
|
152
|
-
|
|
153
|
-
## 4. Core Concepts: State, Operations, and Events
|
|
154
|
-
|
|
155
|
-
After seeing the pin in action, the following sections explain **how** it works internally.
|
|
156
|
-
|
|
157
|
-
### 4.1 State
|
|
158
|
-
|
|
159
|
-
The **Pin** component uses both **internal properties** and **DOM attributes** to manage its state. This ensures consistency whether you modify the pin via script or HTML attributes.
|
|
160
|
-
|
|
161
|
-
#### 4.1.1 Definition
|
|
162
|
-
|
|
163
|
-
- **`visible`** (`yes` | `no`)
|
|
164
|
-
|
|
165
|
-
- Whether the pin is displayed.
|
|
166
|
-
- **Not-initialized** by default, meaning the component reverts to an internal default (`yes`) if `visible` is absent.
|
|
167
|
-
|
|
168
|
-
- **`status`** (`pinned` | `unpinned`)
|
|
169
|
-
- Whether the pin is pinned or unpinned.
|
|
170
|
-
- **Initialized** by default, so if `<pin-button status="pinned">` is found at startup, it remains pinned initially.
|
|
171
|
-
|
|
172
|
-
#### 4.1.2 Internal vs. Attribute-Driven State
|
|
173
|
-
|
|
174
|
-
1. **Internal State**
|
|
175
|
-
|
|
176
|
-
```typescript
|
|
177
|
-
private _visible: Visibility = Visible.YES;
|
|
178
|
-
private _status: Statuses = Status.UNPINNED;
|
|
179
|
-
```
|
|
180
|
-
|
|
181
|
-
- Predictable defaults decoupled from external attributes.
|
|
182
|
-
|
|
183
|
-
2. **Attribute-Driven State**
|
|
184
|
-
```typescript
|
|
185
|
-
public get visible(): Visibility {
|
|
186
|
-
return this.hasAttribute(Attribute.VISIBLE)
|
|
187
|
-
? (this.getAttribute(Attribute.VISIBLE) as Visibility)
|
|
188
|
-
: this._visible;
|
|
189
|
-
}
|
|
190
|
-
public set visible(visible: Visibility) {
|
|
191
|
-
visible = visible || Visible.YES; // fallback
|
|
192
|
-
if (this._visible !== visible) {
|
|
193
|
-
this._visible = visible;
|
|
194
|
-
visible === Visible.YES && this.removeAttribute(Attribute.VISIBLE);
|
|
195
|
-
visible === Visible.NO && this.setAttribute(Attribute.VISIBLE, visible);
|
|
196
|
-
}
|
|
197
|
-
}
|
|
198
|
-
```
|
|
199
|
-
- Keeps `_visible` in sync with `[visible="no"]` if you set it in HTML or JS.
|
|
200
|
-
|
|
201
|
-
#### 4.1.3 Lifecycle & Attribute Handlers
|
|
202
|
-
|
|
203
|
-
- `_initialize()` sets internal defaults on connect.
|
|
204
|
-
- `attributeChangedCallback()` invokes `_attributeHandlers`, updating state when external attributes change.
|
|
205
|
-
|
|
206
|
-
#### 4.1.4 Usage Tips
|
|
207
|
-
|
|
208
|
-
- **Fallback**: Removing `[visible="no"]` reverts to `YES`.
|
|
209
|
-
- **Clean DOM**: If `visible` is `YES`, no attribute is present.
|
|
210
|
-
|
|
211
|
-
---
|
|
212
|
-
|
|
213
|
-
### 4.2 Operations
|
|
214
|
-
|
|
215
|
-
The **Pin** component’s imperative API manipulates state, which in turn updates the DOM and triggers events.
|
|
216
|
-
|
|
217
|
-
#### 4.2.1 Definition
|
|
218
|
-
|
|
219
|
-
1. `hide()` → `visible="no"`
|
|
220
|
-
2. `show()` → `visible="yes"`
|
|
221
|
-
3. `pin()` → `status="pinned"`
|
|
222
|
-
4. `unpin()` → `status="unpinned"`
|
|
223
|
-
5. `toggle()` → flips between pinned/unpinned
|
|
224
|
-
|
|
225
|
-
#### 4.2.2 Example
|
|
226
|
-
|
|
227
|
-
```typescript
|
|
228
|
-
public toggle = () => (
|
|
229
|
-
this.status = this.status === Status.PINNED ? Status.UNPINNED : Status.PINNED
|
|
230
|
-
);
|
|
231
|
-
```
|
|
232
|
-
|
|
233
|
-
---
|
|
234
|
-
|
|
235
|
-
### 4.3 Events
|
|
236
|
-
|
|
237
|
-
The **Pin** component broadcasts custom events when its internal state changes.
|
|
238
|
-
|
|
239
|
-
#### 4.3.1 Definition
|
|
240
|
-
|
|
241
|
-
- **`onhide`**: Fired when going from visible to hidden.
|
|
242
|
-
- **`onshow`**: Fired when going from hidden to visible.
|
|
243
|
-
- **`onpin`**: Fired when going from unpinned to pinned.
|
|
244
|
-
- **`onunpin`**: Fired when going from pinned to unpinned.
|
|
245
|
-
- **`on`**: A catch-all for any of the above changes.
|
|
246
|
-
|
|
247
|
-
#### 4.3.2 Usage Tips
|
|
248
|
-
|
|
249
|
-
- Assign a handler:
|
|
250
|
-
|
|
251
|
-
```js
|
|
252
|
-
pin.onpin = (event) => console.log(event.detail.status);
|
|
253
|
-
```
|
|
254
|
-
|
|
255
|
-
- Or use standard DOM events:
|
|
256
|
-
|
|
257
|
-
```js
|
|
258
|
-
pin.addEventListener("onpin", (e) => {
|
|
259
|
-
// ...
|
|
260
|
-
});
|
|
261
|
-
```
|
|
262
|
-
|
|
263
|
-
---
|
|
264
|
-
|
|
265
|
-
## 5. Development Workflow
|
|
266
|
-
|
|
267
|
-
Below is a recommended workflow for building, testing, documenting, and publishing the Pin component:
|
|
268
|
-
|
|
269
|
-
### 5.1 From Specifications to Implementation
|
|
270
|
-
|
|
271
|
-
1. **Define Specs** (states, operations, events).
|
|
272
|
-
2. **Implement** in TypeScript (reflect states as attributes, dispatch events on changes).
|
|
273
|
-
3. **Link** the final compiled JS or leverage import maps.
|
|
274
|
-
|
|
275
|
-
### 5.2 Testing
|
|
276
|
-
|
|
277
|
-
- **Unit Tests** using Karma + Jasmine or real-time Wallaby.
|
|
278
|
-
- Ensure coverage for states, operations, events.
|
|
279
|
-
- Generate coverage:
|
|
280
|
-
|
|
281
|
-
```bash
|
|
282
|
-
npm test
|
|
283
|
-
```
|
|
284
|
-
|
|
285
|
-
### 5.3 Import Maps
|
|
286
|
-
|
|
287
|
-
```html
|
|
288
|
-
<script type="importmap">
|
|
289
|
-
{
|
|
290
|
-
"imports": {
|
|
291
|
-
"pin-component": "./dist/Pin.js"
|
|
292
|
-
}
|
|
293
|
-
}
|
|
294
|
-
</script>
|
|
295
|
-
<script type="module">
|
|
296
|
-
import "pin-component";
|
|
297
|
-
</script>
|
|
298
|
-
```
|
|
299
|
-
|
|
300
|
-
### 5.4 Documentation (Typedoc)
|
|
301
|
-
|
|
302
|
-
```bash
|
|
303
|
-
npm run document
|
|
304
|
-
```
|
|
305
|
-
|
|
306
|
-
- Auto-generates API docs from TypeScript annotations.
|
|
307
|
-
|
|
308
|
-
### 5.5 Publishing & Versioning
|
|
309
|
-
|
|
310
|
-
1. **Build**:
|
|
311
|
-
|
|
312
|
-
```bash
|
|
313
|
-
npm run build
|
|
314
|
-
```
|
|
315
|
-
|
|
316
|
-
→ outputs `dist/`.
|
|
317
|
-
|
|
318
|
-
2. **Bump Version**:
|
|
319
|
-
|
|
320
|
-
```bash
|
|
321
|
-
npm version [major|minor|patch]
|
|
322
|
-
```
|
|
323
|
-
|
|
324
|
-
3. **Publish**:
|
|
325
|
-
```bash
|
|
326
|
-
npm publish
|
|
327
|
-
```
|
|
328
|
-
to npm or private registry.
|
|
329
|
-
|
|
330
|
-
---
|
|
331
|
-
|
|
332
|
-
## 6. Best Practices & Extensibility
|
|
333
|
-
|
|
334
|
-
1. **Descriptive Naming**
|
|
335
|
-
|
|
336
|
-
- `pinned/unpinned` is domain-friendly for toggles.
|
|
337
|
-
|
|
338
|
-
2. **Accessibility**
|
|
339
|
-
|
|
340
|
-
- Consider ARIA attributes and keyboard interactions if you want `<pin-button>` fully accessible as a toggle/button.
|
|
341
|
-
|
|
342
|
-
3. **Testing**
|
|
343
|
-
|
|
344
|
-
- Simulate user clicks/touches to confirm correct state changes and event dispatch.
|
|
345
|
-
|
|
346
|
-
4. **Documentation**
|
|
347
|
-
|
|
348
|
-
- Provide real usage snippets (like in the Quick Start) for developer onboarding.
|
|
349
|
-
|
|
350
|
-
5. **Publishing**
|
|
351
|
-
- Use semantic versioning to manage features/breaking changes.
|
|
352
|
-
- Employ CI/CD for automated build/test/publish.
|
|
353
|
-
|
|
354
|
-
---
|
|
355
|
-
|
|
356
|
-
## 7. Conclusion
|
|
357
|
-
|
|
358
|
-
By showing you how to **pin** or **unpin** the component immediately (in the Usage Walkthrough), we’ve demonstrated its core features. Internally, the **Pin** component’s **State**, **Operations**, and **Events** ensure predictable, event-driven functionality. Follow the **development workflow** for specs, build, test, docs, and publishing to confidently integrate `<pin-button>` into your projects.
|
|
359
|
-
|
|
360
|
-
---
|
|
361
|
-
|
|
362
|
-
### License
|
|
363
|
-
|
|
364
|
-
> This document is released under the **Creative Commons Attribution-NonCommercial-ShareAlike 4.0 International** (CC BY-NC-SA 4.0) license.
|
|
365
|
-
> For more details, please visit the [license agreement](https://creativecommons.org/licenses/by-nc-sa/4.0/).
|
|
1
|
+
# Pin Component Documentation
|
|
2
|
+
|
|
3
|
+
Below is a **comprehensive** document detailing the **Pin** component’s architecture, usage, and developer workflow. It prioritizes a **Quick Start** so you can see the pin in action right away, then dives into **State**, **Operations**, **Events**, and more advanced topics.
|
|
4
|
+
|
|
5
|
+
---
|
|
6
|
+
|
|
7
|
+
## 1. Introduction
|
|
8
|
+
|
|
9
|
+
The **Pin** component provides a toggleable element that can be pinned/unpinned and hidden/shown via both **imperative** and **declarative** APIs. It leverages custom Web Component features, including Shadow DOM, custom events, and attribute reflection for a clean, modular design.
|
|
10
|
+
|
|
11
|
+
### 1.1 Installation & Setup
|
|
12
|
+
|
|
13
|
+
1. **Clone the Repository**
|
|
14
|
+
|
|
15
|
+
```bash
|
|
16
|
+
git clone <repository-url>
|
|
17
|
+
cd pin-component
|
|
18
|
+
```
|
|
19
|
+
|
|
20
|
+
2. **Install Dependencies**
|
|
21
|
+
|
|
22
|
+
```bash
|
|
23
|
+
npm install
|
|
24
|
+
```
|
|
25
|
+
|
|
26
|
+
3. **Run Tests (Optional)**
|
|
27
|
+
|
|
28
|
+
```bash
|
|
29
|
+
npm test
|
|
30
|
+
```
|
|
31
|
+
|
|
32
|
+
- Ensures everything is working as expected before you start.
|
|
33
|
+
|
|
34
|
+
4. **Start Local Server**
|
|
35
|
+
```bash
|
|
36
|
+
npm run serve
|
|
37
|
+
```
|
|
38
|
+
- This runs a local development server, making `<pin-button>` available in your browser.
|
|
39
|
+
|
|
40
|
+
---
|
|
41
|
+
|
|
42
|
+
## 2. Quick Start Usage Walkthrough
|
|
43
|
+
|
|
44
|
+
This walkthrough demonstrates how to interact with `<pin-button>` right after installation, letting you see how the pin behaves before exploring its internal design.
|
|
45
|
+
|
|
46
|
+
1. **Open** the served page in your browser.
|
|
47
|
+
|
|
48
|
+
- You should see a `<pin-button>` component displayed.
|
|
49
|
+
|
|
50
|
+
2. **Open the Developer Tools**, select the **Console**.
|
|
51
|
+
|
|
52
|
+
3. **Get a reference** to the component:
|
|
53
|
+
|
|
54
|
+
```js
|
|
55
|
+
const pin = document.querySelector("pin-button");
|
|
56
|
+
```
|
|
57
|
+
|
|
58
|
+
4. **Create a handler** for when the pin is pinned:
|
|
59
|
+
|
|
60
|
+
```js
|
|
61
|
+
const onpin = (event) => {
|
|
62
|
+
console.log("Pin was pinned:", event.detail.status);
|
|
63
|
+
};
|
|
64
|
+
```
|
|
65
|
+
|
|
66
|
+
5. **Assign** that handler to the `onpin` property:
|
|
67
|
+
|
|
68
|
+
```js
|
|
69
|
+
pin.onpin = onpin;
|
|
70
|
+
```
|
|
71
|
+
|
|
72
|
+
6. **Pin** the component imperatively:
|
|
73
|
+
|
|
74
|
+
```js
|
|
75
|
+
pin.pin();
|
|
76
|
+
```
|
|
77
|
+
|
|
78
|
+
- This changes `status` from `unpinned` to `pinned`.
|
|
79
|
+
- Observe the console output: `"Pin was pinned: pinned"`.
|
|
80
|
+
|
|
81
|
+
7. **Inspect** the `<pin-button>` in the **Elements** tab:
|
|
82
|
+
|
|
83
|
+
```html
|
|
84
|
+
<pin-button status="pinned"></pin-button>
|
|
85
|
+
```
|
|
86
|
+
|
|
87
|
+
8. **Manually change** the `status` attribute to `"unpinned"`
|
|
88
|
+
|
|
89
|
+
- Notice the pin’s icon and internal state update.
|
|
90
|
+
|
|
91
|
+
9. **Check** the current status in the console:
|
|
92
|
+
|
|
93
|
+
```js
|
|
94
|
+
pin.status; // Should return "unpinned"
|
|
95
|
+
```
|
|
96
|
+
|
|
97
|
+
10. **Click** the `<pin-button>` in the UI
|
|
98
|
+
|
|
99
|
+
- By default, clicking toggles it between `pinned` and `unpinned`.
|
|
100
|
+
- If pinned, the `onpin` event is fired (if you have a listener).
|
|
101
|
+
|
|
102
|
+
11. **Check** the status again:
|
|
103
|
+
|
|
104
|
+
```js
|
|
105
|
+
pin.status; // "pinned" or "unpinned"
|
|
106
|
+
```
|
|
107
|
+
|
|
108
|
+
> **Visibility**
|
|
109
|
+
>
|
|
110
|
+
> - You can similarly call `pin.hide()` or `pin.show()` to toggle the `visible` state.
|
|
111
|
+
> - Watch for `onhide` or `onshow` events in the console.
|
|
112
|
+
|
|
113
|
+
For more details on **States**, **Operations**, and **Events**, consult the sections below or check the generated **API documentation** (see `npm run document` instructions).
|
|
114
|
+
|
|
115
|
+
---
|
|
116
|
+
|
|
117
|
+
## 3. Architectural Overview
|
|
118
|
+
|
|
119
|
+
### 3.1 Composition
|
|
120
|
+
|
|
121
|
+
- **Template** (e.g., `Pin.template.html`):
|
|
122
|
+
Defines DOM structure (a `.icon` container, pinned/unpinned SVGs, etc.).
|
|
123
|
+
|
|
124
|
+
- **Style** (e.g., `Pin.style.css`):
|
|
125
|
+
Encapsulates appearance, including hover effects, pinned/unpinned icon transitions.
|
|
126
|
+
|
|
127
|
+
- **Class** (`Pin.ts`):
|
|
128
|
+
Extends a base component class to handle lifecycle hooks, Shadow DOM creation, attribute reflection, etc.
|
|
129
|
+
|
|
130
|
+
> **Separation of Concerns**
|
|
131
|
+
>
|
|
132
|
+
> - **HTML** for structure
|
|
133
|
+
> - **CSS** for presentation
|
|
134
|
+
> - **TypeScript** for behavior
|
|
135
|
+
|
|
136
|
+
### 3.2 Class Lifecycle
|
|
137
|
+
|
|
138
|
+
Lifecycle methods are implemented in the base class and extended by the **Pin** component:
|
|
139
|
+
|
|
140
|
+
- **`connectedCallback()`**
|
|
141
|
+
|
|
142
|
+
1. Creates a Shadow DOM.
|
|
143
|
+
2. Clones the HTML template into the Shadow Root.
|
|
144
|
+
3. Inserts a `<link>` for scoped CSS.
|
|
145
|
+
4. Initializes default states (`visible`, `status`).
|
|
146
|
+
5. Sets up event listeners (e.g., on click).
|
|
147
|
+
|
|
148
|
+
- **`disconnectedCallback()`**
|
|
149
|
+
- Removes event listeners and cleans up references.
|
|
150
|
+
|
|
151
|
+
---
|
|
152
|
+
|
|
153
|
+
## 4. Core Concepts: State, Operations, and Events
|
|
154
|
+
|
|
155
|
+
After seeing the pin in action, the following sections explain **how** it works internally.
|
|
156
|
+
|
|
157
|
+
### 4.1 State
|
|
158
|
+
|
|
159
|
+
The **Pin** component uses both **internal properties** and **DOM attributes** to manage its state. This ensures consistency whether you modify the pin via script or HTML attributes.
|
|
160
|
+
|
|
161
|
+
#### 4.1.1 Definition
|
|
162
|
+
|
|
163
|
+
- **`visible`** (`yes` | `no`)
|
|
164
|
+
|
|
165
|
+
- Whether the pin is displayed.
|
|
166
|
+
- **Not-initialized** by default, meaning the component reverts to an internal default (`yes`) if `visible` is absent.
|
|
167
|
+
|
|
168
|
+
- **`status`** (`pinned` | `unpinned`)
|
|
169
|
+
- Whether the pin is pinned or unpinned.
|
|
170
|
+
- **Initialized** by default, so if `<pin-button status="pinned">` is found at startup, it remains pinned initially.
|
|
171
|
+
|
|
172
|
+
#### 4.1.2 Internal vs. Attribute-Driven State
|
|
173
|
+
|
|
174
|
+
1. **Internal State**
|
|
175
|
+
|
|
176
|
+
```typescript
|
|
177
|
+
private _visible: Visibility = Visible.YES;
|
|
178
|
+
private _status: Statuses = Status.UNPINNED;
|
|
179
|
+
```
|
|
180
|
+
|
|
181
|
+
- Predictable defaults decoupled from external attributes.
|
|
182
|
+
|
|
183
|
+
2. **Attribute-Driven State**
|
|
184
|
+
```typescript
|
|
185
|
+
public get visible(): Visibility {
|
|
186
|
+
return this.hasAttribute(Attribute.VISIBLE)
|
|
187
|
+
? (this.getAttribute(Attribute.VISIBLE) as Visibility)
|
|
188
|
+
: this._visible;
|
|
189
|
+
}
|
|
190
|
+
public set visible(visible: Visibility) {
|
|
191
|
+
visible = visible || Visible.YES; // fallback
|
|
192
|
+
if (this._visible !== visible) {
|
|
193
|
+
this._visible = visible;
|
|
194
|
+
visible === Visible.YES && this.removeAttribute(Attribute.VISIBLE);
|
|
195
|
+
visible === Visible.NO && this.setAttribute(Attribute.VISIBLE, visible);
|
|
196
|
+
}
|
|
197
|
+
}
|
|
198
|
+
```
|
|
199
|
+
- Keeps `_visible` in sync with `[visible="no"]` if you set it in HTML or JS.
|
|
200
|
+
|
|
201
|
+
#### 4.1.3 Lifecycle & Attribute Handlers
|
|
202
|
+
|
|
203
|
+
- `_initialize()` sets internal defaults on connect.
|
|
204
|
+
- `attributeChangedCallback()` invokes `_attributeHandlers`, updating state when external attributes change.
|
|
205
|
+
|
|
206
|
+
#### 4.1.4 Usage Tips
|
|
207
|
+
|
|
208
|
+
- **Fallback**: Removing `[visible="no"]` reverts to `YES`.
|
|
209
|
+
- **Clean DOM**: If `visible` is `YES`, no attribute is present.
|
|
210
|
+
|
|
211
|
+
---
|
|
212
|
+
|
|
213
|
+
### 4.2 Operations
|
|
214
|
+
|
|
215
|
+
The **Pin** component’s imperative API manipulates state, which in turn updates the DOM and triggers events.
|
|
216
|
+
|
|
217
|
+
#### 4.2.1 Definition
|
|
218
|
+
|
|
219
|
+
1. `hide()` → `visible="no"`
|
|
220
|
+
2. `show()` → `visible="yes"`
|
|
221
|
+
3. `pin()` → `status="pinned"`
|
|
222
|
+
4. `unpin()` → `status="unpinned"`
|
|
223
|
+
5. `toggle()` → flips between pinned/unpinned
|
|
224
|
+
|
|
225
|
+
#### 4.2.2 Example
|
|
226
|
+
|
|
227
|
+
```typescript
|
|
228
|
+
public toggle = () => (
|
|
229
|
+
this.status = this.status === Status.PINNED ? Status.UNPINNED : Status.PINNED
|
|
230
|
+
);
|
|
231
|
+
```
|
|
232
|
+
|
|
233
|
+
---
|
|
234
|
+
|
|
235
|
+
### 4.3 Events
|
|
236
|
+
|
|
237
|
+
The **Pin** component broadcasts custom events when its internal state changes.
|
|
238
|
+
|
|
239
|
+
#### 4.3.1 Definition
|
|
240
|
+
|
|
241
|
+
- **`onhide`**: Fired when going from visible to hidden.
|
|
242
|
+
- **`onshow`**: Fired when going from hidden to visible.
|
|
243
|
+
- **`onpin`**: Fired when going from unpinned to pinned.
|
|
244
|
+
- **`onunpin`**: Fired when going from pinned to unpinned.
|
|
245
|
+
- **`on`**: A catch-all for any of the above changes.
|
|
246
|
+
|
|
247
|
+
#### 4.3.2 Usage Tips
|
|
248
|
+
|
|
249
|
+
- Assign a handler:
|
|
250
|
+
|
|
251
|
+
```js
|
|
252
|
+
pin.onpin = (event) => console.log(event.detail.status);
|
|
253
|
+
```
|
|
254
|
+
|
|
255
|
+
- Or use standard DOM events:
|
|
256
|
+
|
|
257
|
+
```js
|
|
258
|
+
pin.addEventListener("onpin", (e) => {
|
|
259
|
+
// ...
|
|
260
|
+
});
|
|
261
|
+
```
|
|
262
|
+
|
|
263
|
+
---
|
|
264
|
+
|
|
265
|
+
## 5. Development Workflow
|
|
266
|
+
|
|
267
|
+
Below is a recommended workflow for building, testing, documenting, and publishing the Pin component:
|
|
268
|
+
|
|
269
|
+
### 5.1 From Specifications to Implementation
|
|
270
|
+
|
|
271
|
+
1. **Define Specs** (states, operations, events).
|
|
272
|
+
2. **Implement** in TypeScript (reflect states as attributes, dispatch events on changes).
|
|
273
|
+
3. **Link** the final compiled JS or leverage import maps.
|
|
274
|
+
|
|
275
|
+
### 5.2 Testing
|
|
276
|
+
|
|
277
|
+
- **Unit Tests** using Karma + Jasmine or real-time Wallaby.
|
|
278
|
+
- Ensure coverage for states, operations, events.
|
|
279
|
+
- Generate coverage:
|
|
280
|
+
|
|
281
|
+
```bash
|
|
282
|
+
npm test
|
|
283
|
+
```
|
|
284
|
+
|
|
285
|
+
### 5.3 Import Maps
|
|
286
|
+
|
|
287
|
+
```html
|
|
288
|
+
<script type="importmap">
|
|
289
|
+
{
|
|
290
|
+
"imports": {
|
|
291
|
+
"pin-component": "./dist/Pin.js"
|
|
292
|
+
}
|
|
293
|
+
}
|
|
294
|
+
</script>
|
|
295
|
+
<script type="module">
|
|
296
|
+
import "pin-component";
|
|
297
|
+
</script>
|
|
298
|
+
```
|
|
299
|
+
|
|
300
|
+
### 5.4 Documentation (Typedoc)
|
|
301
|
+
|
|
302
|
+
```bash
|
|
303
|
+
npm run document
|
|
304
|
+
```
|
|
305
|
+
|
|
306
|
+
- Auto-generates API docs from TypeScript annotations.
|
|
307
|
+
|
|
308
|
+
### 5.5 Publishing & Versioning
|
|
309
|
+
|
|
310
|
+
1. **Build**:
|
|
311
|
+
|
|
312
|
+
```bash
|
|
313
|
+
npm run build
|
|
314
|
+
```
|
|
315
|
+
|
|
316
|
+
→ outputs `dist/`.
|
|
317
|
+
|
|
318
|
+
2. **Bump Version**:
|
|
319
|
+
|
|
320
|
+
```bash
|
|
321
|
+
npm version [major|minor|patch]
|
|
322
|
+
```
|
|
323
|
+
|
|
324
|
+
3. **Publish**:
|
|
325
|
+
```bash
|
|
326
|
+
npm publish
|
|
327
|
+
```
|
|
328
|
+
to npm or private registry.
|
|
329
|
+
|
|
330
|
+
---
|
|
331
|
+
|
|
332
|
+
## 6. Best Practices & Extensibility
|
|
333
|
+
|
|
334
|
+
1. **Descriptive Naming**
|
|
335
|
+
|
|
336
|
+
- `pinned/unpinned` is domain-friendly for toggles.
|
|
337
|
+
|
|
338
|
+
2. **Accessibility**
|
|
339
|
+
|
|
340
|
+
- Consider ARIA attributes and keyboard interactions if you want `<pin-button>` fully accessible as a toggle/button.
|
|
341
|
+
|
|
342
|
+
3. **Testing**
|
|
343
|
+
|
|
344
|
+
- Simulate user clicks/touches to confirm correct state changes and event dispatch.
|
|
345
|
+
|
|
346
|
+
4. **Documentation**
|
|
347
|
+
|
|
348
|
+
- Provide real usage snippets (like in the Quick Start) for developer onboarding.
|
|
349
|
+
|
|
350
|
+
5. **Publishing**
|
|
351
|
+
- Use semantic versioning to manage features/breaking changes.
|
|
352
|
+
- Employ CI/CD for automated build/test/publish.
|
|
353
|
+
|
|
354
|
+
---
|
|
355
|
+
|
|
356
|
+
## 7. Conclusion
|
|
357
|
+
|
|
358
|
+
By showing you how to **pin** or **unpin** the component immediately (in the Usage Walkthrough), we’ve demonstrated its core features. Internally, the **Pin** component’s **State**, **Operations**, and **Events** ensure predictable, event-driven functionality. Follow the **development workflow** for specs, build, test, docs, and publishing to confidently integrate `<pin-button>` into your projects.
|
|
359
|
+
|
|
360
|
+
---
|
|
361
|
+
|
|
362
|
+
### License
|
|
363
|
+
|
|
364
|
+
> This document is released under the **Creative Commons Attribution-NonCommercial-ShareAlike 4.0 International** (CC BY-NC-SA 4.0) license.
|
|
365
|
+
> For more details, please visit the [license agreement](https://creativecommons.org/licenses/by-nc-sa/4.0/).
|