@phcdevworks/spectre-components 0.0.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 +21 -0
- package/README.md +177 -0
- package/dist/button.cjs +288 -0
- package/dist/button.cjs.map +1 -0
- package/dist/button.d.cts +142 -0
- package/dist/button.d.ts +142 -0
- package/dist/button.js +282 -0
- package/dist/button.js.map +1 -0
- package/dist/checkbox.cjs +158 -0
- package/dist/checkbox.cjs.map +1 -0
- package/dist/checkbox.d.cts +98 -0
- package/dist/checkbox.d.ts +98 -0
- package/dist/checkbox.js +155 -0
- package/dist/checkbox.js.map +1 -0
- package/dist/fieldset.cjs +179 -0
- package/dist/fieldset.cjs.map +1 -0
- package/dist/fieldset.d.cts +63 -0
- package/dist/fieldset.d.ts +63 -0
- package/dist/fieldset.js +176 -0
- package/dist/fieldset.js.map +1 -0
- package/dist/index.cjs +1600 -0
- package/dist/index.cjs.map +1 -0
- package/dist/index.d.cts +14 -0
- package/dist/index.d.ts +14 -0
- package/dist/index.js +1576 -0
- package/dist/index.js.map +1 -0
- package/dist/input.cjs +235 -0
- package/dist/input.cjs.map +1 -0
- package/dist/input.d.cts +175 -0
- package/dist/input.d.ts +175 -0
- package/dist/input.js +230 -0
- package/dist/input.js.map +1 -0
- package/dist/label.cjs +156 -0
- package/dist/label.cjs.map +1 -0
- package/dist/label.d.cts +39 -0
- package/dist/label.d.ts +39 -0
- package/dist/label.js +153 -0
- package/dist/label.js.map +1 -0
- package/dist/radio.cjs +158 -0
- package/dist/radio.cjs.map +1 -0
- package/dist/radio.d.cts +98 -0
- package/dist/radio.d.ts +98 -0
- package/dist/radio.js +155 -0
- package/dist/radio.js.map +1 -0
- package/dist/select.cjs +272 -0
- package/dist/select.cjs.map +1 -0
- package/dist/select.d.cts +130 -0
- package/dist/select.d.ts +130 -0
- package/dist/select.js +268 -0
- package/dist/select.js.map +1 -0
- package/dist/textarea.cjs +423 -0
- package/dist/textarea.cjs.map +1 -0
- package/dist/textarea.d.cts +156 -0
- package/dist/textarea.d.ts +156 -0
- package/dist/textarea.js +420 -0
- package/dist/textarea.js.map +1 -0
- package/package.json +124 -0
package/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 PHCDevworks
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
package/README.md
ADDED
|
@@ -0,0 +1,177 @@
|
|
|
1
|
+
# @phcdevworks/spectre-components
|
|
2
|
+
|
|
3
|
+
[](https://github.com/phcdevworks/spectre-components/issues)
|
|
4
|
+
[](https://github.com/phcdevworks/spectre-components/pulls)
|
|
5
|
+
[](LICENSE)
|
|
6
|
+
|
|
7
|
+
`@phcdevworks/spectre-components` is the Lit-based component layer of the
|
|
8
|
+
Spectre suite.
|
|
9
|
+
|
|
10
|
+
Maintained by PHCDevworks, it turns Spectre tokens and Spectre UI contracts
|
|
11
|
+
into reusable, accessible, framework-agnostic web components. It is the
|
|
12
|
+
canonical component implementation layer for Spectre, built on platform
|
|
13
|
+
standards and designed to be consumed directly or wrapped later by adapter
|
|
14
|
+
packages.
|
|
15
|
+
|
|
16
|
+
## Key capabilities
|
|
17
|
+
|
|
18
|
+
- Ships reusable web components implemented with Lit
|
|
19
|
+
- Consumes `@phcdevworks/spectre-tokens` as the source of visual meaning
|
|
20
|
+
- Consumes `@phcdevworks/spectre-ui` as the styling contract layer
|
|
21
|
+
- Keeps component delivery framework-agnostic through custom elements
|
|
22
|
+
- Builds accessibility into the initial component patterns
|
|
23
|
+
- Exposes a small, explicit API surface suitable for long-term growth
|
|
24
|
+
|
|
25
|
+
## Installation
|
|
26
|
+
|
|
27
|
+
```bash
|
|
28
|
+
npm install @phcdevworks/spectre-components @phcdevworks/spectre-ui @phcdevworks/spectre-tokens
|
|
29
|
+
```
|
|
30
|
+
|
|
31
|
+
## Quick start
|
|
32
|
+
|
|
33
|
+
Import the Spectre CSS layers first, then register the custom elements you want
|
|
34
|
+
to use:
|
|
35
|
+
|
|
36
|
+
```ts
|
|
37
|
+
import "@phcdevworks/spectre-tokens/index.css";
|
|
38
|
+
import "@phcdevworks/spectre-ui/index.css";
|
|
39
|
+
|
|
40
|
+
import { defineSpectreComponents } from "@phcdevworks/spectre-components";
|
|
41
|
+
|
|
42
|
+
defineSpectreComponents();
|
|
43
|
+
```
|
|
44
|
+
|
|
45
|
+
Use the components in markup:
|
|
46
|
+
|
|
47
|
+
```html
|
|
48
|
+
<sp-button variant="primary" size="md">Save</sp-button>
|
|
49
|
+
<sp-button variant="ghost" size="sm">Cancel</sp-button>
|
|
50
|
+
<sp-input name="email" type="email" placeholder="Email address"></sp-input>
|
|
51
|
+
```
|
|
52
|
+
|
|
53
|
+
Register only the button when you want a narrower entry point:
|
|
54
|
+
|
|
55
|
+
```ts
|
|
56
|
+
import { defineSpectreButton } from "@phcdevworks/spectre-components/button";
|
|
57
|
+
|
|
58
|
+
defineSpectreButton();
|
|
59
|
+
```
|
|
60
|
+
|
|
61
|
+
Register only the input when you want the input-only entry point:
|
|
62
|
+
|
|
63
|
+
```ts
|
|
64
|
+
import { defineSpectreInput } from "@phcdevworks/spectre-components/input";
|
|
65
|
+
|
|
66
|
+
defineSpectreInput();
|
|
67
|
+
```
|
|
68
|
+
|
|
69
|
+
## What this package owns
|
|
70
|
+
|
|
71
|
+
- Lit-based web component implementation for Spectre
|
|
72
|
+
- Accessible component behavior and DOM structure
|
|
73
|
+
- Public custom element registration helpers
|
|
74
|
+
- Component-level TypeScript APIs for future adapters to build on
|
|
75
|
+
|
|
76
|
+
Golden rule: implement components from Spectre contracts, do not redefine those
|
|
77
|
+
contracts locally.
|
|
78
|
+
|
|
79
|
+
## What this package does not own
|
|
80
|
+
|
|
81
|
+
- Design-token values or semantic visual meaning That belongs to
|
|
82
|
+
[`@phcdevworks/spectre-tokens`](https://github.com/phcdevworks/spectre-tokens).
|
|
83
|
+
- CSS utilities, class recipes, or styling contracts That belongs to
|
|
84
|
+
[`@phcdevworks/spectre-ui`](https://github.com/phcdevworks/spectre-ui).
|
|
85
|
+
- Framework adapters such as React, Vue, Astro, or app-specific wrappers Those
|
|
86
|
+
belong in downstream adapter packages.
|
|
87
|
+
- Routing, shell logic, manifest behavior, or startup orchestration Those are
|
|
88
|
+
outside the scope of this package.
|
|
89
|
+
|
|
90
|
+
## Package exports / API surface
|
|
91
|
+
|
|
92
|
+
### Root package
|
|
93
|
+
|
|
94
|
+
`@phcdevworks/spectre-components` exports:
|
|
95
|
+
|
|
96
|
+
- `defineSpectreComponents()`
|
|
97
|
+
- `defineSpectreButton()`
|
|
98
|
+
- `defineSpectreInput()`
|
|
99
|
+
- `SpectreButtonElement`
|
|
100
|
+
- `SpectreInputElement`
|
|
101
|
+
- `spectreButtonVariants`
|
|
102
|
+
- `spectreButtonSizes`
|
|
103
|
+
- `spectreButtonTypes`
|
|
104
|
+
- `spectreInputTypes`
|
|
105
|
+
- `spectreInputSizes`
|
|
106
|
+
- `SpectreButtonProps` and related button types
|
|
107
|
+
- `SpectreInputProps` and related input types
|
|
108
|
+
|
|
109
|
+
### Button entry point
|
|
110
|
+
|
|
111
|
+
`@phcdevworks/spectre-components/button` exports the button-only API so
|
|
112
|
+
consumers can register a single component without importing the full package
|
|
113
|
+
entry.
|
|
114
|
+
|
|
115
|
+
### Input entry point
|
|
116
|
+
|
|
117
|
+
`@phcdevworks/spectre-components/input` exports the input-only API so
|
|
118
|
+
consumers can register just `sp-input` when they do not need the broader
|
|
119
|
+
component bundle.
|
|
120
|
+
|
|
121
|
+
## Relationship to the rest of Spectre
|
|
122
|
+
|
|
123
|
+
Spectre keeps responsibilities separate:
|
|
124
|
+
|
|
125
|
+
- [`@phcdevworks/spectre-tokens`](https://github.com/phcdevworks/spectre-tokens)
|
|
126
|
+
defines design values and semantic meaning
|
|
127
|
+
- [`@phcdevworks/spectre-ui`](https://github.com/phcdevworks/spectre-ui)
|
|
128
|
+
provides CSS, Tailwind helpers, recipes, and styling contracts
|
|
129
|
+
- `@phcdevworks/spectre-components` turns those layers into Lit-based reusable
|
|
130
|
+
web components
|
|
131
|
+
|
|
132
|
+
That separation keeps visual meaning centralized, styling contracts stable, and
|
|
133
|
+
component behavior reusable across frameworks.
|
|
134
|
+
|
|
135
|
+
## Current foundation
|
|
136
|
+
|
|
137
|
+
This v0 foundation includes:
|
|
138
|
+
|
|
139
|
+
- a publishable TypeScript package build
|
|
140
|
+
- root and subpath exports
|
|
141
|
+
- a Lit-based `sp-button` starter component
|
|
142
|
+
- a Lit-based `sp-input` foundation component
|
|
143
|
+
- explicit registration helpers instead of implicit global side effects
|
|
144
|
+
- Vitest coverage for baseline rendering and accessibility behavior
|
|
145
|
+
|
|
146
|
+
## Development
|
|
147
|
+
|
|
148
|
+
Install dependencies, then run the package checks:
|
|
149
|
+
|
|
150
|
+
```bash
|
|
151
|
+
npm run build
|
|
152
|
+
npm test
|
|
153
|
+
npm run lint
|
|
154
|
+
```
|
|
155
|
+
|
|
156
|
+
Key source areas:
|
|
157
|
+
|
|
158
|
+
- `src/components/` for custom elements
|
|
159
|
+
- `src/index.ts` for the root public API
|
|
160
|
+
- `tests/` for component behavior coverage
|
|
161
|
+
|
|
162
|
+
## Contributing
|
|
163
|
+
|
|
164
|
+
PHCDevworks maintains this package as part of the Spectre suite.
|
|
165
|
+
|
|
166
|
+
When contributing:
|
|
167
|
+
|
|
168
|
+
- treat `@phcdevworks/spectre-tokens` as the source of visual meaning
|
|
169
|
+
- treat `@phcdevworks/spectre-ui` as the styling contract layer
|
|
170
|
+
- avoid redefining visual primitives locally
|
|
171
|
+
- keep components accessible by default
|
|
172
|
+
- run `npm run build`, `npm test`, and `npm run lint` before opening a pull
|
|
173
|
+
request
|
|
174
|
+
|
|
175
|
+
## License
|
|
176
|
+
|
|
177
|
+
MIT © PHCDevworks. See [LICENSE](LICENSE).
|
package/dist/button.cjs
ADDED
|
@@ -0,0 +1,288 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
var lit = require('lit');
|
|
4
|
+
var ifDefined_js = require('lit/directives/if-defined.js');
|
|
5
|
+
var spectreUi = require('@phcdevworks/spectre-ui');
|
|
6
|
+
|
|
7
|
+
// src/components/button/sp-button.ts
|
|
8
|
+
var spectreButtonVariants = [
|
|
9
|
+
"primary",
|
|
10
|
+
"secondary",
|
|
11
|
+
"ghost",
|
|
12
|
+
"danger",
|
|
13
|
+
"success",
|
|
14
|
+
"cta",
|
|
15
|
+
"accent"
|
|
16
|
+
];
|
|
17
|
+
var spectreButtonSizes = ["sm", "md", "lg"];
|
|
18
|
+
var spectreButtonTypes = ["button", "submit", "reset"];
|
|
19
|
+
function isButtonVariant(value) {
|
|
20
|
+
return spectreButtonVariants.includes(value);
|
|
21
|
+
}
|
|
22
|
+
function isButtonSize(value) {
|
|
23
|
+
return spectreButtonSizes.includes(value);
|
|
24
|
+
}
|
|
25
|
+
function isButtonType(value) {
|
|
26
|
+
return spectreButtonTypes.includes(value);
|
|
27
|
+
}
|
|
28
|
+
function hasMeaningfulContent(nodes) {
|
|
29
|
+
return nodes.some((node) => {
|
|
30
|
+
if (node.nodeType === Node.ELEMENT_NODE) {
|
|
31
|
+
return true;
|
|
32
|
+
}
|
|
33
|
+
if (node.nodeType === Node.TEXT_NODE) {
|
|
34
|
+
return (node.textContent?.trim().length ?? 0) > 0;
|
|
35
|
+
}
|
|
36
|
+
return false;
|
|
37
|
+
});
|
|
38
|
+
}
|
|
39
|
+
var SpectreButtonElement = class extends lit.LitElement {
|
|
40
|
+
constructor() {
|
|
41
|
+
super(...arguments);
|
|
42
|
+
this.ariaLabel = null;
|
|
43
|
+
this.ariaLabelledBy = null;
|
|
44
|
+
this.ariaDescribedBy = null;
|
|
45
|
+
this.autofocus = false;
|
|
46
|
+
this.disabled = false;
|
|
47
|
+
this.fullWidth = false;
|
|
48
|
+
this.loading = false;
|
|
49
|
+
this.loadingLabel = "Loading";
|
|
50
|
+
this.pill = false;
|
|
51
|
+
this.size = "md";
|
|
52
|
+
this.title = "";
|
|
53
|
+
this.type = "button";
|
|
54
|
+
this.variant = "primary";
|
|
55
|
+
// Native slot projection is a Shadow DOM feature, so in light DOM we keep
|
|
56
|
+
// host-provided content reactive by tracking and reusing the host nodes.
|
|
57
|
+
this.projectedContent = [];
|
|
58
|
+
}
|
|
59
|
+
get id() {
|
|
60
|
+
return this._id ?? "";
|
|
61
|
+
}
|
|
62
|
+
set id(value) {
|
|
63
|
+
if ((this._id ?? "") === value) {
|
|
64
|
+
return;
|
|
65
|
+
}
|
|
66
|
+
this._id = value;
|
|
67
|
+
const host = this;
|
|
68
|
+
if (HTMLElement.prototype.hasAttribute.call(host, "id")) {
|
|
69
|
+
HTMLElement.prototype.removeAttribute.call(host, "id");
|
|
70
|
+
}
|
|
71
|
+
this.requestUpdate();
|
|
72
|
+
}
|
|
73
|
+
createRenderRoot() {
|
|
74
|
+
return this;
|
|
75
|
+
}
|
|
76
|
+
connectedCallback() {
|
|
77
|
+
super.connectedCallback();
|
|
78
|
+
const hostId = super.getAttribute("id");
|
|
79
|
+
if (hostId !== null) {
|
|
80
|
+
this.id = hostId;
|
|
81
|
+
}
|
|
82
|
+
this.syncProjectedContent();
|
|
83
|
+
this.startContentObserver();
|
|
84
|
+
}
|
|
85
|
+
getAttribute(qualifiedName) {
|
|
86
|
+
if (qualifiedName === "id") {
|
|
87
|
+
return this.id || null;
|
|
88
|
+
}
|
|
89
|
+
return super.getAttribute(qualifiedName);
|
|
90
|
+
}
|
|
91
|
+
hasAttribute(qualifiedName) {
|
|
92
|
+
if (qualifiedName === "id") {
|
|
93
|
+
return this.id !== "";
|
|
94
|
+
}
|
|
95
|
+
return super.hasAttribute(qualifiedName);
|
|
96
|
+
}
|
|
97
|
+
setAttribute(qualifiedName, value) {
|
|
98
|
+
if (qualifiedName === "id") {
|
|
99
|
+
this.id = value;
|
|
100
|
+
return;
|
|
101
|
+
}
|
|
102
|
+
super.setAttribute(qualifiedName, value);
|
|
103
|
+
}
|
|
104
|
+
removeAttribute(qualifiedName) {
|
|
105
|
+
if (qualifiedName === "id") {
|
|
106
|
+
this.id = "";
|
|
107
|
+
return;
|
|
108
|
+
}
|
|
109
|
+
super.removeAttribute(qualifiedName);
|
|
110
|
+
}
|
|
111
|
+
disconnectedCallback() {
|
|
112
|
+
this.stopContentObserver();
|
|
113
|
+
super.disconnectedCallback();
|
|
114
|
+
}
|
|
115
|
+
willUpdate(changedProperties) {
|
|
116
|
+
if (changedProperties.has("variant") && !isButtonVariant(this.variant)) {
|
|
117
|
+
this.variant = "primary";
|
|
118
|
+
}
|
|
119
|
+
if (changedProperties.has("size") && !isButtonSize(this.size)) {
|
|
120
|
+
this.size = "md";
|
|
121
|
+
}
|
|
122
|
+
if (changedProperties.has("type") && !isButtonType(this.type)) {
|
|
123
|
+
this.type = "button";
|
|
124
|
+
}
|
|
125
|
+
if (changedProperties.has("loadingLabel")) {
|
|
126
|
+
if (this.loadingLabel == null || this.loadingLabel.trim() === "") {
|
|
127
|
+
this.loadingLabel = "Loading";
|
|
128
|
+
}
|
|
129
|
+
}
|
|
130
|
+
}
|
|
131
|
+
update(changedProperties) {
|
|
132
|
+
this.stopContentObserver();
|
|
133
|
+
super.update(changedProperties);
|
|
134
|
+
this.startContentObserver();
|
|
135
|
+
}
|
|
136
|
+
get buttonClasses() {
|
|
137
|
+
return spectreUi.getButtonClasses({
|
|
138
|
+
disabled: this.isDisabled,
|
|
139
|
+
fullWidth: this.fullWidth,
|
|
140
|
+
loading: this.loading,
|
|
141
|
+
pill: this.pill,
|
|
142
|
+
size: this.size,
|
|
143
|
+
variant: this.variant
|
|
144
|
+
});
|
|
145
|
+
}
|
|
146
|
+
get isDisabled() {
|
|
147
|
+
return this.disabled || this.loading;
|
|
148
|
+
}
|
|
149
|
+
get hasProjectedContent() {
|
|
150
|
+
return hasMeaningfulContent(this.projectedContent);
|
|
151
|
+
}
|
|
152
|
+
get visibleLabelFallback() {
|
|
153
|
+
const trimmedLabel = this.label?.trim();
|
|
154
|
+
return trimmedLabel ? trimmedLabel : void 0;
|
|
155
|
+
}
|
|
156
|
+
get forwardedAriaLabel() {
|
|
157
|
+
const ariaLabel = this.ariaLabel?.trim();
|
|
158
|
+
return ariaLabel ? ariaLabel : void 0;
|
|
159
|
+
}
|
|
160
|
+
get forwardedAriaLabelledBy() {
|
|
161
|
+
const ariaLabelledBy = this.ariaLabelledBy?.trim();
|
|
162
|
+
return ariaLabelledBy ? ariaLabelledBy : void 0;
|
|
163
|
+
}
|
|
164
|
+
get forwardedAriaDescribedBy() {
|
|
165
|
+
const ariaDescribedBy = this.ariaDescribedBy?.trim();
|
|
166
|
+
return ariaDescribedBy ? ariaDescribedBy : void 0;
|
|
167
|
+
}
|
|
168
|
+
startContentObserver() {
|
|
169
|
+
if (this.contentObserver) {
|
|
170
|
+
return;
|
|
171
|
+
}
|
|
172
|
+
this.contentObserver = new MutationObserver((mutations) => {
|
|
173
|
+
const isInternalMovement = mutations.every((mutation) => {
|
|
174
|
+
return Array.from(mutation.removedNodes).every(
|
|
175
|
+
(node) => this.isInternalButtonNode(node) || this.contains(node)
|
|
176
|
+
) && Array.from(mutation.addedNodes).every((node) => this.isInternalButtonNode(node));
|
|
177
|
+
});
|
|
178
|
+
if (isInternalMovement) {
|
|
179
|
+
return;
|
|
180
|
+
}
|
|
181
|
+
if (this.syncProjectedContent()) {
|
|
182
|
+
this.requestUpdate();
|
|
183
|
+
}
|
|
184
|
+
});
|
|
185
|
+
this.contentObserver.observe(this, {
|
|
186
|
+
childList: true
|
|
187
|
+
});
|
|
188
|
+
}
|
|
189
|
+
stopContentObserver() {
|
|
190
|
+
this.contentObserver?.disconnect();
|
|
191
|
+
this.contentObserver = void 0;
|
|
192
|
+
}
|
|
193
|
+
syncProjectedContent() {
|
|
194
|
+
const nextProjectedContent = [];
|
|
195
|
+
Array.from(this.childNodes).forEach((node) => {
|
|
196
|
+
if (this.isInternalButtonNode(node)) {
|
|
197
|
+
this.projectedContent.forEach((pNode) => {
|
|
198
|
+
if (pNode.parentNode !== this && this.contains(pNode)) {
|
|
199
|
+
nextProjectedContent.push(pNode);
|
|
200
|
+
}
|
|
201
|
+
});
|
|
202
|
+
} else {
|
|
203
|
+
nextProjectedContent.push(node);
|
|
204
|
+
}
|
|
205
|
+
});
|
|
206
|
+
const hasChanged = nextProjectedContent.length !== this.projectedContent.length || nextProjectedContent.some((node, index) => node !== this.projectedContent[index]);
|
|
207
|
+
if (hasChanged) {
|
|
208
|
+
this.projectedContent = nextProjectedContent;
|
|
209
|
+
}
|
|
210
|
+
return hasChanged;
|
|
211
|
+
}
|
|
212
|
+
isInternalButtonNode(node) {
|
|
213
|
+
return node.nodeType === Node.ELEMENT_NODE && node.hasAttribute("data-sp-button-native");
|
|
214
|
+
}
|
|
215
|
+
get nativeButton() {
|
|
216
|
+
return this.querySelector("[data-sp-button-native]");
|
|
217
|
+
}
|
|
218
|
+
focus(options) {
|
|
219
|
+
this.nativeButton?.focus(options);
|
|
220
|
+
}
|
|
221
|
+
blur() {
|
|
222
|
+
this.nativeButton?.blur();
|
|
223
|
+
}
|
|
224
|
+
renderButtonContent() {
|
|
225
|
+
if (this.loading) {
|
|
226
|
+
return this.loadingLabel;
|
|
227
|
+
}
|
|
228
|
+
if (this.hasProjectedContent) {
|
|
229
|
+
return this.projectedContent;
|
|
230
|
+
}
|
|
231
|
+
return this.visibleLabelFallback ?? "";
|
|
232
|
+
}
|
|
233
|
+
render() {
|
|
234
|
+
return lit.html`
|
|
235
|
+
<button
|
|
236
|
+
aria-busy=${this.loading ? "true" : "false"}
|
|
237
|
+
aria-describedby=${ifDefined_js.ifDefined(this.forwardedAriaDescribedBy)}
|
|
238
|
+
aria-label=${ifDefined_js.ifDefined(this.forwardedAriaLabel)}
|
|
239
|
+
aria-labelledby=${ifDefined_js.ifDefined(this.forwardedAriaLabelledBy)}
|
|
240
|
+
?autofocus=${this.autofocus}
|
|
241
|
+
class=${this.buttonClasses}
|
|
242
|
+
data-sp-button-native
|
|
243
|
+
?disabled=${this.isDisabled}
|
|
244
|
+
id=${ifDefined_js.ifDefined(this.id || void 0)}
|
|
245
|
+
name=${ifDefined_js.ifDefined(this.name)}
|
|
246
|
+
title=${ifDefined_js.ifDefined(this.title || void 0)}
|
|
247
|
+
type=${this.type}
|
|
248
|
+
value=${ifDefined_js.ifDefined(this.value)}
|
|
249
|
+
>
|
|
250
|
+
${this.renderButtonContent() || lit.nothing}
|
|
251
|
+
</button>
|
|
252
|
+
`;
|
|
253
|
+
}
|
|
254
|
+
};
|
|
255
|
+
SpectreButtonElement.properties = {
|
|
256
|
+
ariaLabel: { attribute: "aria-label", type: String },
|
|
257
|
+
ariaLabelledBy: { attribute: "aria-labelledby", type: String },
|
|
258
|
+
ariaDescribedBy: { attribute: "aria-describedby", type: String },
|
|
259
|
+
autofocus: { type: Boolean, reflect: true },
|
|
260
|
+
disabled: { type: Boolean, reflect: true },
|
|
261
|
+
fullWidth: { attribute: "full-width", type: Boolean, reflect: true },
|
|
262
|
+
label: { type: String, reflect: true },
|
|
263
|
+
loading: { type: Boolean, reflect: true },
|
|
264
|
+
loadingLabel: { attribute: "loading-label", type: String, reflect: true },
|
|
265
|
+
name: { type: String, reflect: true },
|
|
266
|
+
pill: { type: Boolean, reflect: true },
|
|
267
|
+
size: { type: String, reflect: true },
|
|
268
|
+
title: { type: String, reflect: true },
|
|
269
|
+
type: { type: String, reflect: true },
|
|
270
|
+
variant: { type: String, reflect: true },
|
|
271
|
+
value: { type: String, reflect: true }
|
|
272
|
+
};
|
|
273
|
+
function defineSpectreButton(tagName = "sp-button") {
|
|
274
|
+
const existingElement = customElements.get(tagName);
|
|
275
|
+
if (existingElement) {
|
|
276
|
+
return existingElement;
|
|
277
|
+
}
|
|
278
|
+
customElements.define(tagName, SpectreButtonElement);
|
|
279
|
+
return SpectreButtonElement;
|
|
280
|
+
}
|
|
281
|
+
|
|
282
|
+
exports.SpectreButtonElement = SpectreButtonElement;
|
|
283
|
+
exports.defineSpectreButton = defineSpectreButton;
|
|
284
|
+
exports.spectreButtonSizes = spectreButtonSizes;
|
|
285
|
+
exports.spectreButtonTypes = spectreButtonTypes;
|
|
286
|
+
exports.spectreButtonVariants = spectreButtonVariants;
|
|
287
|
+
//# sourceMappingURL=button.cjs.map
|
|
288
|
+
//# sourceMappingURL=button.cjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/components/button/sp-button.ts"],"names":["LitElement","getButtonClasses","html","ifDefined","nothing"],"mappings":"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","file":"button.cjs","sourcesContent":["import { LitElement, html, nothing, type TemplateResult } from 'lit';\nimport { ifDefined } from 'lit/directives/if-defined.js';\n\nimport {\n getButtonClasses,\n type ButtonSize,\n type ButtonVariant,\n} from '@phcdevworks/spectre-ui';\n\nexport const spectreButtonVariants = [\n 'primary',\n 'secondary',\n 'ghost',\n 'danger',\n 'success',\n 'cta',\n 'accent',\n] as const;\n\nexport const spectreButtonSizes = ['sm', 'md', 'lg'] as const;\nexport const spectreButtonTypes = ['button', 'submit', 'reset'] as const;\n\nexport type SpectreButtonVariant = (typeof spectreButtonVariants)[number];\nexport type SpectreButtonSize = (typeof spectreButtonSizes)[number];\nexport type SpectreButtonType = (typeof spectreButtonTypes)[number];\n\nexport interface SpectreButtonProps {\n autofocus?: boolean;\n disabled?: boolean;\n fullWidth?: boolean;\n label?: string;\n loading?: boolean;\n loadingLabel?: string;\n name?: string;\n pill?: boolean;\n size?: SpectreButtonSize;\n title?: string;\n type?: SpectreButtonType;\n variant?: SpectreButtonVariant;\n value?: string;\n}\n\nfunction isButtonVariant(value: string): value is ButtonVariant {\n return (spectreButtonVariants as readonly string[]).includes(value);\n}\n\nfunction isButtonSize(value: string): value is ButtonSize {\n return (spectreButtonSizes as readonly string[]).includes(value);\n}\n\nfunction isButtonType(value: string): value is SpectreButtonType {\n return (spectreButtonTypes as readonly string[]).includes(value);\n}\n\nfunction hasMeaningfulContent(nodes: readonly Node[]): boolean {\n return nodes.some((node) => {\n if (node.nodeType === Node.ELEMENT_NODE) {\n return true;\n }\n\n if (node.nodeType === Node.TEXT_NODE) {\n return (node.textContent?.trim().length ?? 0) > 0;\n }\n\n return false;\n });\n}\n\nexport class SpectreButtonElement extends LitElement implements SpectreButtonProps {\n static properties = {\n ariaLabel: { attribute: 'aria-label', type: String },\n ariaLabelledBy: { attribute: 'aria-labelledby', type: String },\n ariaDescribedBy: { attribute: 'aria-describedby', type: String },\n autofocus: { type: Boolean, reflect: true },\n disabled: { type: Boolean, reflect: true },\n fullWidth: { attribute: 'full-width', type: Boolean, reflect: true },\n label: { type: String, reflect: true },\n loading: { type: Boolean, reflect: true },\n loadingLabel: { attribute: 'loading-label', type: String, reflect: true },\n name: { type: String, reflect: true },\n pill: { type: Boolean, reflect: true },\n size: { type: String, reflect: true },\n title: { type: String, reflect: true },\n type: { type: String, reflect: true },\n variant: { type: String, reflect: true },\n value: { type: String, reflect: true },\n };\n\n ariaLabel: string | null = null;\n ariaLabelledBy: string | null = null;\n ariaDescribedBy: string | null = null;\n autofocus = false;\n disabled = false;\n fullWidth = false;\n label?: string;\n loading = false;\n loadingLabel = 'Loading';\n name?: string;\n pill = false;\n size: SpectreButtonSize = 'md';\n override title = '';\n type: SpectreButtonType = 'button';\n variant: SpectreButtonVariant = 'primary';\n value?: string;\n private _id?: string;\n\n override get id(): string {\n return this._id ?? '';\n }\n\n override set id(value: string) {\n if ((this._id ?? '') === value) {\n return;\n }\n\n this._id = value;\n\n const host = this as unknown as HTMLElement;\n if (HTMLElement.prototype.hasAttribute.call(host, 'id')) {\n HTMLElement.prototype.removeAttribute.call(host, 'id');\n }\n\n this.requestUpdate();\n }\n\n // Native slot projection is a Shadow DOM feature, so in light DOM we keep\n // host-provided content reactive by tracking and reusing the host nodes.\n private projectedContent: Node[] = [];\n private contentObserver?: MutationObserver | undefined;\n\n createRenderRoot(): this {\n // Spectre components intentionally render in light DOM so the global\n // `@phcdevworks/spectre-ui` styling contract can apply directly.\n return this;\n }\n\n override connectedCallback(): void {\n super.connectedCallback();\n\n const hostId = super.getAttribute('id');\n\n if (hostId !== null) {\n this.id = hostId;\n }\n\n this.syncProjectedContent();\n this.startContentObserver();\n }\n\n override getAttribute(qualifiedName: string): string | null {\n if (qualifiedName === 'id') {\n return this.id || null;\n }\n\n return super.getAttribute(qualifiedName);\n }\n\n override hasAttribute(qualifiedName: string): boolean {\n if (qualifiedName === 'id') {\n return this.id !== '';\n }\n\n return super.hasAttribute(qualifiedName);\n }\n\n override setAttribute(qualifiedName: string, value: string): void {\n if (qualifiedName === 'id') {\n this.id = value;\n return;\n }\n\n super.setAttribute(qualifiedName, value);\n }\n\n override removeAttribute(qualifiedName: string): void {\n if (qualifiedName === 'id') {\n this.id = '';\n return;\n }\n\n super.removeAttribute(qualifiedName);\n }\n\n override disconnectedCallback(): void {\n this.stopContentObserver();\n super.disconnectedCallback();\n }\n\n protected override willUpdate(changedProperties: Map<PropertyKey, unknown>): void {\n if (changedProperties.has('variant') && !isButtonVariant(this.variant)) {\n this.variant = 'primary';\n }\n\n if (changedProperties.has('size') && !isButtonSize(this.size)) {\n this.size = 'md';\n }\n\n if (changedProperties.has('type') && !isButtonType(this.type)) {\n this.type = 'button';\n }\n\n if (changedProperties.has('loadingLabel')) {\n if (this.loadingLabel == null || this.loadingLabel.trim() === '') {\n this.loadingLabel = 'Loading';\n }\n }\n }\n\n protected override update(changedProperties: Map<PropertyKey, unknown>): void {\n this.stopContentObserver();\n super.update(changedProperties);\n this.startContentObserver();\n }\n\n private get buttonClasses(): string {\n return getButtonClasses({\n disabled: this.isDisabled,\n fullWidth: this.fullWidth,\n loading: this.loading,\n pill: this.pill,\n size: this.size,\n variant: this.variant,\n });\n }\n\n private get isDisabled(): boolean {\n return this.disabled || this.loading;\n }\n\n private get hasProjectedContent(): boolean {\n return hasMeaningfulContent(this.projectedContent);\n }\n\n private get visibleLabelFallback(): string | undefined {\n const trimmedLabel = this.label?.trim();\n return trimmedLabel ? trimmedLabel : undefined;\n }\n\n private get forwardedAriaLabel(): string | undefined {\n const ariaLabel = this.ariaLabel?.trim();\n return ariaLabel ? ariaLabel : undefined;\n }\n\n private get forwardedAriaLabelledBy(): string | undefined {\n const ariaLabelledBy = this.ariaLabelledBy?.trim();\n return ariaLabelledBy ? ariaLabelledBy : undefined;\n }\n\n private get forwardedAriaDescribedBy(): string | undefined {\n const ariaDescribedBy = this.ariaDescribedBy?.trim();\n return ariaDescribedBy ? ariaDescribedBy : undefined;\n }\n\n private startContentObserver(): void {\n if (this.contentObserver) {\n return;\n }\n\n this.contentObserver = new MutationObserver((mutations) => {\n const isInternalMovement = mutations.every((mutation) => {\n return (\n Array.from(mutation.removedNodes).every(\n (node) => this.isInternalButtonNode(node) || this.contains(node),\n ) &&\n Array.from(mutation.addedNodes).every((node) => this.isInternalButtonNode(node))\n );\n });\n\n if (isInternalMovement) {\n return;\n }\n\n if (this.syncProjectedContent()) {\n this.requestUpdate();\n }\n });\n\n this.contentObserver.observe(this, {\n childList: true,\n });\n }\n\n private stopContentObserver(): void {\n this.contentObserver?.disconnect();\n this.contentObserver = undefined;\n }\n\n private syncProjectedContent(): boolean {\n const nextProjectedContent: Node[] = [];\n\n Array.from(this.childNodes).forEach((node) => {\n if (this.isInternalButtonNode(node)) {\n this.projectedContent.forEach((pNode) => {\n if (pNode.parentNode !== this && this.contains(pNode)) {\n nextProjectedContent.push(pNode);\n }\n });\n } else {\n nextProjectedContent.push(node);\n }\n });\n\n const hasChanged =\n nextProjectedContent.length !== this.projectedContent.length ||\n nextProjectedContent.some((node, index) => node !== this.projectedContent[index]);\n\n if (hasChanged) {\n this.projectedContent = nextProjectedContent;\n }\n\n return hasChanged;\n }\n\n private isInternalButtonNode(node: Node): boolean {\n return (\n node.nodeType === Node.ELEMENT_NODE && (node as Element).hasAttribute('data-sp-button-native')\n );\n }\n\n private get nativeButton(): HTMLButtonElement | null {\n return this.querySelector('[data-sp-button-native]');\n }\n\n override focus(options?: FocusOptions): void {\n this.nativeButton?.focus(options);\n }\n\n override blur(): void {\n this.nativeButton?.blur();\n }\n\n private renderButtonContent(): TemplateResult | Node[] | string {\n if (this.loading) {\n return this.loadingLabel;\n }\n\n if (this.hasProjectedContent) {\n return this.projectedContent;\n }\n\n return this.visibleLabelFallback ?? '';\n }\n\n override render() {\n return html`\n <button\n aria-busy=${this.loading ? 'true' : 'false'}\n aria-describedby=${ifDefined(this.forwardedAriaDescribedBy)}\n aria-label=${ifDefined(this.forwardedAriaLabel)}\n aria-labelledby=${ifDefined(this.forwardedAriaLabelledBy)}\n ?autofocus=${this.autofocus}\n class=${this.buttonClasses}\n data-sp-button-native\n ?disabled=${this.isDisabled}\n id=${ifDefined(this.id || undefined)}\n name=${ifDefined(this.name)}\n title=${ifDefined(this.title || undefined)}\n type=${this.type}\n value=${ifDefined(this.value)}\n >\n ${this.renderButtonContent() || nothing}\n </button>\n `;\n }\n}\n\nexport function defineSpectreButton(tagName = 'sp-button'): typeof SpectreButtonElement {\n const existingElement = customElements.get(tagName);\n\n if (existingElement) {\n return existingElement as unknown as typeof SpectreButtonElement;\n }\n\n customElements.define(tagName, SpectreButtonElement);\n return SpectreButtonElement;\n}\n"]}
|
|
@@ -0,0 +1,142 @@
|
|
|
1
|
+
import { LitElement, TemplateResult } from 'lit';
|
|
2
|
+
|
|
3
|
+
declare const spectreButtonVariants: readonly ["primary", "secondary", "ghost", "danger", "success", "cta", "accent"];
|
|
4
|
+
declare const spectreButtonSizes: readonly ["sm", "md", "lg"];
|
|
5
|
+
declare const spectreButtonTypes: readonly ["button", "submit", "reset"];
|
|
6
|
+
type SpectreButtonVariant = (typeof spectreButtonVariants)[number];
|
|
7
|
+
type SpectreButtonSize = (typeof spectreButtonSizes)[number];
|
|
8
|
+
type SpectreButtonType = (typeof spectreButtonTypes)[number];
|
|
9
|
+
interface SpectreButtonProps {
|
|
10
|
+
autofocus?: boolean;
|
|
11
|
+
disabled?: boolean;
|
|
12
|
+
fullWidth?: boolean;
|
|
13
|
+
label?: string;
|
|
14
|
+
loading?: boolean;
|
|
15
|
+
loadingLabel?: string;
|
|
16
|
+
name?: string;
|
|
17
|
+
pill?: boolean;
|
|
18
|
+
size?: SpectreButtonSize;
|
|
19
|
+
title?: string;
|
|
20
|
+
type?: SpectreButtonType;
|
|
21
|
+
variant?: SpectreButtonVariant;
|
|
22
|
+
value?: string;
|
|
23
|
+
}
|
|
24
|
+
declare class SpectreButtonElement extends LitElement implements SpectreButtonProps {
|
|
25
|
+
static properties: {
|
|
26
|
+
ariaLabel: {
|
|
27
|
+
attribute: string;
|
|
28
|
+
type: StringConstructor;
|
|
29
|
+
};
|
|
30
|
+
ariaLabelledBy: {
|
|
31
|
+
attribute: string;
|
|
32
|
+
type: StringConstructor;
|
|
33
|
+
};
|
|
34
|
+
ariaDescribedBy: {
|
|
35
|
+
attribute: string;
|
|
36
|
+
type: StringConstructor;
|
|
37
|
+
};
|
|
38
|
+
autofocus: {
|
|
39
|
+
type: BooleanConstructor;
|
|
40
|
+
reflect: boolean;
|
|
41
|
+
};
|
|
42
|
+
disabled: {
|
|
43
|
+
type: BooleanConstructor;
|
|
44
|
+
reflect: boolean;
|
|
45
|
+
};
|
|
46
|
+
fullWidth: {
|
|
47
|
+
attribute: string;
|
|
48
|
+
type: BooleanConstructor;
|
|
49
|
+
reflect: boolean;
|
|
50
|
+
};
|
|
51
|
+
label: {
|
|
52
|
+
type: StringConstructor;
|
|
53
|
+
reflect: boolean;
|
|
54
|
+
};
|
|
55
|
+
loading: {
|
|
56
|
+
type: BooleanConstructor;
|
|
57
|
+
reflect: boolean;
|
|
58
|
+
};
|
|
59
|
+
loadingLabel: {
|
|
60
|
+
attribute: string;
|
|
61
|
+
type: StringConstructor;
|
|
62
|
+
reflect: boolean;
|
|
63
|
+
};
|
|
64
|
+
name: {
|
|
65
|
+
type: StringConstructor;
|
|
66
|
+
reflect: boolean;
|
|
67
|
+
};
|
|
68
|
+
pill: {
|
|
69
|
+
type: BooleanConstructor;
|
|
70
|
+
reflect: boolean;
|
|
71
|
+
};
|
|
72
|
+
size: {
|
|
73
|
+
type: StringConstructor;
|
|
74
|
+
reflect: boolean;
|
|
75
|
+
};
|
|
76
|
+
title: {
|
|
77
|
+
type: StringConstructor;
|
|
78
|
+
reflect: boolean;
|
|
79
|
+
};
|
|
80
|
+
type: {
|
|
81
|
+
type: StringConstructor;
|
|
82
|
+
reflect: boolean;
|
|
83
|
+
};
|
|
84
|
+
variant: {
|
|
85
|
+
type: StringConstructor;
|
|
86
|
+
reflect: boolean;
|
|
87
|
+
};
|
|
88
|
+
value: {
|
|
89
|
+
type: StringConstructor;
|
|
90
|
+
reflect: boolean;
|
|
91
|
+
};
|
|
92
|
+
};
|
|
93
|
+
ariaLabel: string | null;
|
|
94
|
+
ariaLabelledBy: string | null;
|
|
95
|
+
ariaDescribedBy: string | null;
|
|
96
|
+
autofocus: boolean;
|
|
97
|
+
disabled: boolean;
|
|
98
|
+
fullWidth: boolean;
|
|
99
|
+
label?: string;
|
|
100
|
+
loading: boolean;
|
|
101
|
+
loadingLabel: string;
|
|
102
|
+
name?: string;
|
|
103
|
+
pill: boolean;
|
|
104
|
+
size: SpectreButtonSize;
|
|
105
|
+
title: string;
|
|
106
|
+
type: SpectreButtonType;
|
|
107
|
+
variant: SpectreButtonVariant;
|
|
108
|
+
value?: string;
|
|
109
|
+
private _id?;
|
|
110
|
+
get id(): string;
|
|
111
|
+
set id(value: string);
|
|
112
|
+
private projectedContent;
|
|
113
|
+
private contentObserver?;
|
|
114
|
+
createRenderRoot(): this;
|
|
115
|
+
connectedCallback(): void;
|
|
116
|
+
getAttribute(qualifiedName: string): string | null;
|
|
117
|
+
hasAttribute(qualifiedName: string): boolean;
|
|
118
|
+
setAttribute(qualifiedName: string, value: string): void;
|
|
119
|
+
removeAttribute(qualifiedName: string): void;
|
|
120
|
+
disconnectedCallback(): void;
|
|
121
|
+
protected willUpdate(changedProperties: Map<PropertyKey, unknown>): void;
|
|
122
|
+
protected update(changedProperties: Map<PropertyKey, unknown>): void;
|
|
123
|
+
private get buttonClasses();
|
|
124
|
+
private get isDisabled();
|
|
125
|
+
private get hasProjectedContent();
|
|
126
|
+
private get visibleLabelFallback();
|
|
127
|
+
private get forwardedAriaLabel();
|
|
128
|
+
private get forwardedAriaLabelledBy();
|
|
129
|
+
private get forwardedAriaDescribedBy();
|
|
130
|
+
private startContentObserver;
|
|
131
|
+
private stopContentObserver;
|
|
132
|
+
private syncProjectedContent;
|
|
133
|
+
private isInternalButtonNode;
|
|
134
|
+
private get nativeButton();
|
|
135
|
+
focus(options?: FocusOptions): void;
|
|
136
|
+
blur(): void;
|
|
137
|
+
private renderButtonContent;
|
|
138
|
+
render(): TemplateResult<1>;
|
|
139
|
+
}
|
|
140
|
+
declare function defineSpectreButton(tagName?: string): typeof SpectreButtonElement;
|
|
141
|
+
|
|
142
|
+
export { SpectreButtonElement, type SpectreButtonProps, type SpectreButtonSize, type SpectreButtonType, type SpectreButtonVariant, defineSpectreButton, spectreButtonSizes, spectreButtonTypes, spectreButtonVariants };
|