@transcodes/ui-components 0.3.0 → 0.3.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.
Files changed (46) hide show
  1. package/CHANGELOG.md +76 -0
  2. package/README.md +124 -79
  3. package/dist/controllers/animation.controller.js +32 -0
  4. package/dist/controllers/base.controller.js +8 -0
  5. package/dist/controllers/form-validation.controller.js +49 -0
  6. package/dist/controllers/history.controller.js +26 -0
  7. package/dist/controllers/loading.controller.js +27 -0
  8. package/dist/controllers/match-media.controller.js +20 -0
  9. package/dist/controllers/message-bus.controller.js +45 -0
  10. package/dist/controllers/storage.controller.js +40 -0
  11. package/dist/index.js +80 -0
  12. package/dist/primitives/tc-box.js +38 -0
  13. package/dist/primitives/tc-button.js +167 -0
  14. package/dist/primitives/tc-callout.js +86 -0
  15. package/dist/primitives/tc-card.js +76 -0
  16. package/dist/primitives/tc-chip.js +79 -0
  17. package/dist/primitives/tc-container.js +62 -0
  18. package/dist/primitives/tc-divider.js +76 -0
  19. package/dist/primitives/tc-error-message.js +74 -0
  20. package/dist/primitives/tc-form-header.js +120 -0
  21. package/dist/primitives/tc-icon.js +95 -0
  22. package/dist/primitives/tc-input-with-chip.js +242 -0
  23. package/dist/primitives/tc-input.js +262 -0
  24. package/dist/primitives/tc-item-button.js +168 -0
  25. package/dist/primitives/tc-item.js +93 -0
  26. package/dist/primitives/tc-otp-input.js +230 -0
  27. package/dist/primitives/tc-section.js +48 -0
  28. package/dist/primitives/tc-spinner.js +87 -0
  29. package/dist/primitives/tc-symbol.js +56 -0
  30. package/dist/primitives/tc-text.js +145 -0
  31. package/dist/primitives/tc-toast.js +189 -0
  32. package/dist/screens/tc-error-screen.js +119 -0
  33. package/dist/screens/tc-loading-screen.js +77 -0
  34. package/dist/screens/tc-success-screen.js +192 -0
  35. package/dist/styles/shared.js +7 -0
  36. package/dist/widgets/tc-authenticator-card.js +213 -0
  37. package/dist/widgets/tc-floating-button.js +132 -0
  38. package/dist/widgets/tc-iframe-modal.js +263 -0
  39. package/dist/widgets/tc-installation-banner.js +234 -0
  40. package/dist/widgets/tc-ios-installation-guide.js +240 -0
  41. package/dist/widgets/tc-notification-modal.js +230 -0
  42. package/dist/widgets/tc-offline-modal.js +202 -0
  43. package/dist/widgets/tc-page-decoration.js +126 -0
  44. package/package.json +25 -7
  45. package/dist/ui-components.css +0 -1
  46. package/dist/ui-components.js +0 -4981
@@ -0,0 +1,230 @@
1
+ import { LitElement as u, html as h, css as p } from "lit";
2
+ import { property as c, state as d, customElement as v } from "lit/decorators.js";
3
+ import { sharedStyles as m } from "../styles/shared.js";
4
+ var g = Object.defineProperty, f = Object.getOwnPropertyDescriptor, n = (t, e, s, r) => {
5
+ for (var a = r > 1 ? void 0 : r ? f(e, s) : e, o = t.length - 1, l; o >= 0; o--)
6
+ (l = t[o]) && (a = (r ? l(e, s, a) : l(a)) || a);
7
+ return r && a && g(e, s, a), a;
8
+ };
9
+ let i = class extends u {
10
+ constructor() {
11
+ super(...arguments), this.length = 6, this.error = !1, this.disabled = !1, this.showProgress = !0, this.values = [];
12
+ }
13
+ connectedCallback() {
14
+ super.connectedCallback(), this.values = new Array(this.length).fill("");
15
+ }
16
+ render() {
17
+ const e = this.values.filter((s) => s.length > 0).length / this.length * 100;
18
+ return h`
19
+ <div class="container">
20
+ <div part="cells" class="cells" role="group" aria-label="OTP input">
21
+ ${this.values.map((s, r) => {
22
+ const o = [
23
+ "cell",
24
+ s.length > 0 ? "cell--filled" : "",
25
+ this.error ? "cell--error" : ""
26
+ ].filter(Boolean).join(" ");
27
+ return h`
28
+ <input
29
+ part="cell"
30
+ class=${o}
31
+ type="text"
32
+ inputmode="numeric"
33
+ maxlength="1"
34
+ pattern="[0-9]"
35
+ .value=${s}
36
+ ?disabled=${this.disabled}
37
+ aria-label="Digit ${r + 1}"
38
+ @input=${(l) => this.handleInput(l, r)}
39
+ @keydown=${(l) => this.handleKeydown(l, r)}
40
+ @paste=${(l) => this.handlePaste(l)}
41
+ />
42
+ `;
43
+ })}
44
+ </div>
45
+ ${this.showProgress ? h`
46
+ <div part="progress" class="progress">
47
+ <div
48
+ part="progress-bar"
49
+ class="progress-bar"
50
+ style="width: ${e}%"
51
+ ></div>
52
+ </div>
53
+ ` : ""}
54
+ </div>
55
+ `;
56
+ }
57
+ handleInput(t, e) {
58
+ const r = t.target.value.replace(/\D/g, "").slice(0, 1);
59
+ this.values = [...this.values], this.values[e] = r, this.dispatchEvent(
60
+ new CustomEvent("tc-change", {
61
+ bubbles: !0,
62
+ composed: !0,
63
+ detail: { value: this.values.join(""), values: [...this.values] }
64
+ })
65
+ ), r && e < this.length - 1 && this.focusCell(e + 1), this.values.every((a) => a.length > 0) && this.dispatchEvent(
66
+ new CustomEvent("tc-complete", {
67
+ bubbles: !0,
68
+ composed: !0,
69
+ detail: { value: this.values.join("") }
70
+ })
71
+ );
72
+ }
73
+ handleKeydown(t, e) {
74
+ t.key === "Backspace" && !this.values[e] && e > 0 ? (t.preventDefault(), this.values = [...this.values], this.values[e - 1] = "", this.focusCell(e - 1)) : t.key === "ArrowLeft" && e > 0 ? (t.preventDefault(), this.focusCell(e - 1)) : t.key === "ArrowRight" && e < this.length - 1 && (t.preventDefault(), this.focusCell(e + 1));
75
+ }
76
+ handlePaste(t) {
77
+ t.preventDefault();
78
+ const s = (t.clipboardData?.getData("text") || "").replace(/\D/g, "").slice(0, this.length);
79
+ if (s) {
80
+ this.values = new Array(this.length).fill(""), s.split("").forEach((a, o) => {
81
+ this.values[o] = a;
82
+ }), this.values = [...this.values];
83
+ const r = Math.min(s.length, this.length - 1);
84
+ this.focusCell(r), this.dispatchEvent(
85
+ new CustomEvent("tc-change", {
86
+ bubbles: !0,
87
+ composed: !0,
88
+ detail: { value: this.values.join(""), values: [...this.values] }
89
+ })
90
+ ), s.length >= this.length && this.dispatchEvent(
91
+ new CustomEvent("tc-complete", {
92
+ bubbles: !0,
93
+ composed: !0,
94
+ detail: { value: this.values.join("") }
95
+ })
96
+ );
97
+ }
98
+ }
99
+ focusCell(t) {
100
+ requestAnimationFrame(() => {
101
+ this.shadowRoot?.querySelectorAll(
102
+ ".cell"
103
+ )?.[t]?.focus();
104
+ });
105
+ }
106
+ /** Focus the first empty cell or the last cell */
107
+ focus() {
108
+ const t = this.values.findIndex((s) => !s), e = t >= 0 ? t : this.length - 1;
109
+ this.focusCell(e);
110
+ }
111
+ /** Clear all values */
112
+ clear() {
113
+ this.values = new Array(this.length).fill(""), this.focusCell(0);
114
+ }
115
+ /** Get the current OTP value */
116
+ getValue() {
117
+ return this.values.join("");
118
+ }
119
+ };
120
+ i.styles = [
121
+ m,
122
+ p`
123
+ :host {
124
+ display: block;
125
+ }
126
+
127
+ .container {
128
+ display: flex;
129
+ flex-direction: column;
130
+ align-items: center;
131
+ gap: var(--space-md);
132
+ }
133
+
134
+ .cells {
135
+ display: flex;
136
+ gap: var(--space-sm);
137
+ justify-content: center;
138
+ }
139
+
140
+ .cell {
141
+ width: clamp(2.625rem, 2.35rem + 1.36vw, 3rem);
142
+ height: clamp(3.125rem, 2.78rem + 1.74vw, 3.5rem);
143
+ border: var(--size-border-width-thick) solid transparent;
144
+ border-radius: var(--radius-md);
145
+ background: var(--paper-cream);
146
+ font-family: var(--font-body);
147
+ font-size: clamp(1.25rem, 1.14rem + 0.54vw, 1.5rem);
148
+ font-weight: 600;
149
+ text-align: center;
150
+ color: var(--ink-black);
151
+ transition: all var(--duration-instant) ease;
152
+ caret-color: var(--accent-primary);
153
+ }
154
+
155
+ .cell:focus {
156
+ outline: none;
157
+ background: var(--paper-white);
158
+ border-color: var(--accent-primary);
159
+ box-shadow: var(--shadow-otp-cell-focus);
160
+ }
161
+
162
+ .cell--filled {
163
+ background: var(--paper-white);
164
+ border-color: var(--ink-faint);
165
+ }
166
+
167
+ .cell--error {
168
+ border-color: var(--error-base) !important;
169
+ animation: shake var(--duration-smooth) ease;
170
+ }
171
+
172
+ .cell:disabled {
173
+ opacity: var(--opacity-disabled);
174
+ cursor: not-allowed;
175
+ }
176
+
177
+ /* Progress bar */
178
+ .progress {
179
+ width: 100%;
180
+ max-width: 12rem;
181
+ height: var(--size-border-width-heavy);
182
+ background: var(--paper-warm);
183
+ border-radius: var(--radius-full);
184
+ overflow: hidden;
185
+ }
186
+
187
+ .progress-bar {
188
+ height: 100%;
189
+ background: linear-gradient(
190
+ 90deg,
191
+ var(--accent-primary) 0%,
192
+ var(--accent-primary-hover) 100%
193
+ );
194
+ transition: width var(--duration-instant) ease;
195
+ }
196
+
197
+ /* Reduced motion */
198
+ @media (prefers-reduced-motion: reduce) {
199
+ .cell,
200
+ .progress-bar {
201
+ transition-duration: 0.01ms !important;
202
+ }
203
+
204
+ .cell--error {
205
+ animation: none;
206
+ }
207
+ }
208
+ `
209
+ ];
210
+ n([
211
+ c({ type: Number })
212
+ ], i.prototype, "length", 2);
213
+ n([
214
+ c({ type: Boolean })
215
+ ], i.prototype, "error", 2);
216
+ n([
217
+ c({ type: Boolean })
218
+ ], i.prototype, "disabled", 2);
219
+ n([
220
+ c({ type: Boolean, attribute: "show-progress" })
221
+ ], i.prototype, "showProgress", 2);
222
+ n([
223
+ d()
224
+ ], i.prototype, "values", 2);
225
+ i = n([
226
+ v("tc-otp-input")
227
+ ], i);
228
+ export {
229
+ i as TcOtpInput
230
+ };
@@ -0,0 +1,48 @@
1
+ import { LitElement as a, html as m, css as y } from "lit";
2
+ import { property as n, customElement as f } from "lit/decorators.js";
3
+ import { styleMap as h } from "lit/directives/style-map.js";
4
+ var u = Object.defineProperty, d = Object.getOwnPropertyDescriptor, l = (s, r, p, o) => {
5
+ for (var t = o > 1 ? void 0 : o ? d(r, p) : r, c = s.length - 1, i; c >= 0; c--)
6
+ (i = s[c]) && (t = (o ? i(r, p, t) : i(t)) || t);
7
+ return o && t && u(r, p, t), t;
8
+ };
9
+ let e = class extends a {
10
+ constructor() {
11
+ super(...arguments), this.gap = "var(--space-md)", this.sx = {};
12
+ }
13
+ render() {
14
+ const s = {
15
+ gap: this.gap,
16
+ ...this.sx
17
+ };
18
+ return m`
19
+ <section part="section" class="section" style=${h(s)}>
20
+ <slot></slot>
21
+ </section>
22
+ `;
23
+ }
24
+ };
25
+ e.styles = y`
26
+ :host {
27
+ display: block;
28
+ width: 100%;
29
+ }
30
+
31
+ .section {
32
+ display: flex;
33
+ flex-direction: column;
34
+ width: 100%;
35
+ }
36
+ `;
37
+ l([
38
+ n({ type: String })
39
+ ], e.prototype, "gap", 2);
40
+ l([
41
+ n({ type: Object })
42
+ ], e.prototype, "sx", 2);
43
+ e = l([
44
+ f("tc-section")
45
+ ], e);
46
+ export {
47
+ e as TcSection
48
+ };
@@ -0,0 +1,87 @@
1
+ import { LitElement as d, html as h, css as m } from "lit";
2
+ import { property as l, customElement as c } from "lit/decorators.js";
3
+ import { MatchMediaController as v } from "../controllers/match-media.controller.js";
4
+ import { sharedStyles as b } from "../styles/shared.js";
5
+ var w = Object.defineProperty, z = Object.getOwnPropertyDescriptor, a = (e, s, n, t) => {
6
+ for (var r = t > 1 ? void 0 : t ? z(s, n) : s, o = e.length - 1, p; o >= 0; o--)
7
+ (p = e[o]) && (r = (t ? p(s, n, r) : p(r)) || r);
8
+ return t && r && w(s, n, r), r;
9
+ };
10
+ let i = class extends d {
11
+ constructor() {
12
+ super(...arguments), this.mobile = new v(this, "(max-width: 768px)"), this.size = "auto", this.color = "var(--accent-primary)";
13
+ }
14
+ render() {
15
+ let e;
16
+ return this.size === "auto" ? e = this.mobile.matches ? "spinner--auto-mobile" : "spinner--auto-desktop" : e = `spinner--${this.size}`, h`
17
+ <div
18
+ part="spinner"
19
+ class="spinner ${e}"
20
+ style="--spinner-color: ${this.color};"
21
+ role="progressbar"
22
+ aria-label="Loading"
23
+ ></div>
24
+ `;
25
+ }
26
+ };
27
+ i.styles = [
28
+ b,
29
+ m`
30
+ :host {
31
+ display: inline-flex;
32
+ align-items: center;
33
+ justify-content: center;
34
+ }
35
+
36
+ .spinner {
37
+ display: block;
38
+ border-radius: 50%;
39
+ border-style: solid;
40
+ border-color: var(--paper-cream);
41
+ border-top-color: var(--spinner-color);
42
+ animation: spin var(--duration-slow) linear infinite;
43
+ }
44
+
45
+ .spinner--sm {
46
+ width: var(--size-spinner-sm);
47
+ height: var(--size-spinner-sm);
48
+ border-width: var(--size-border-width-thick);
49
+ }
50
+
51
+ .spinner--md {
52
+ width: var(--size-spinner-md);
53
+ height: var(--size-spinner-md);
54
+ border-width: var(--size-border-width-heavy);
55
+ }
56
+
57
+ .spinner--lg {
58
+ width: var(--size-spinner-lg);
59
+ height: var(--size-spinner-lg);
60
+ border-width: var(--size-border-width-bold);
61
+ }
62
+
63
+ .spinner--auto-mobile {
64
+ width: var(--size-spinner-lg);
65
+ height: var(--size-spinner-lg);
66
+ border-width: var(--size-border-width-heavy);
67
+ }
68
+
69
+ .spinner--auto-desktop {
70
+ width: 5rem;
71
+ height: 5rem;
72
+ border-width: var(--size-border-width-bold);
73
+ }
74
+ `
75
+ ];
76
+ a([
77
+ l({ type: String })
78
+ ], i.prototype, "size", 2);
79
+ a([
80
+ l({ type: String })
81
+ ], i.prototype, "color", 2);
82
+ i = a([
83
+ c("tc-spinner")
84
+ ], i);
85
+ export {
86
+ i as TcSpinner
87
+ };
@@ -0,0 +1,56 @@
1
+ import { LitElement as m, html as p, css as c } from "lit";
2
+ import { property as a, customElement as b } from "lit/decorators.js";
3
+ var v = Object.defineProperty, f = Object.getOwnPropertyDescriptor, s = (y, t, l, e) => {
4
+ for (var r = e > 1 ? void 0 : e ? f(t, l) : t, i = y.length - 1, n; i >= 0; i--)
5
+ (n = y[i]) && (r = (e ? n(t, l, r) : n(r)) || r);
6
+ return e && r && v(t, l, r), r;
7
+ };
8
+ let o = class extends m {
9
+ constructor() {
10
+ super(...arguments), this.size = "3rem", this.background = "var(--paper-cream)", this.color = "var(--ink-dark)";
11
+ }
12
+ render() {
13
+ return p`
14
+ <div
15
+ part="symbol"
16
+ class="symbol"
17
+ style="--symbol-size: ${this.size}; --symbol-bg: ${this.background}; --symbol-color: ${this.color};"
18
+ >
19
+ <slot></slot>
20
+ </div>
21
+ `;
22
+ }
23
+ };
24
+ o.styles = c`
25
+ :host {
26
+ display: inline-flex;
27
+ }
28
+
29
+ .symbol {
30
+ display: flex;
31
+ align-items: center;
32
+ justify-content: center;
33
+ border-radius: var(--radius-full);
34
+ background: var(--symbol-bg);
35
+ color: var(--symbol-color);
36
+ width: var(--symbol-size);
37
+ height: var(--symbol-size);
38
+ font-family: var(--font-body);
39
+ font-weight: 600;
40
+ }
41
+ `;
42
+ s([
43
+ a({ type: String })
44
+ ], o.prototype, "size", 2);
45
+ s([
46
+ a({ type: String })
47
+ ], o.prototype, "background", 2);
48
+ s([
49
+ a({ type: String })
50
+ ], o.prototype, "color", 2);
51
+ o = s([
52
+ b("tc-symbol")
53
+ ], o);
54
+ export {
55
+ o as TcSymbol
56
+ };
@@ -0,0 +1,145 @@
1
+ import { LitElement as x, css as p } from "lit";
2
+ import { property as a, customElement as g } from "lit/decorators.js";
3
+ import { styleMap as h } from "lit/directives/style-map.js";
4
+ import { unsafeStatic as f, html as m } from "lit/static-html.js";
5
+ import { sharedStyles as y } from "../styles/shared.js";
6
+ var v = Object.defineProperty, u = Object.getOwnPropertyDescriptor, n = (r, o, s, i) => {
7
+ for (var e = i > 1 ? void 0 : i ? u(o, s) : o, c = r.length - 1, l; c >= 0; c--)
8
+ (l = r[c]) && (e = (i ? l(o, s, e) : l(e)) || e);
9
+ return i && e && v(o, s, e), e;
10
+ };
11
+ let t = class extends x {
12
+ constructor() {
13
+ super(...arguments), this.tag = "p", this.sx = {};
14
+ }
15
+ getColorClass() {
16
+ return this.color && {
17
+ primary: "text--primary",
18
+ secondary: "text--secondary",
19
+ tertiary: "text--tertiary",
20
+ muted: "text--muted",
21
+ accent: "text--accent",
22
+ success: "text--success",
23
+ error: "text--error",
24
+ warning: "text--warning",
25
+ info: "text--info"
26
+ }[this.color] || "";
27
+ }
28
+ getColorStyle() {
29
+ if (this.color && (this.color.startsWith("var(") || this.color.startsWith("#") || this.color.startsWith("rgb")))
30
+ return this.color;
31
+ }
32
+ render() {
33
+ const r = f(this.tag), o = [
34
+ "text",
35
+ this.size ? `text--${this.size}` : "",
36
+ this.weight ? `text--w${this.weight}` : "",
37
+ this.getColorClass()
38
+ ].filter(Boolean).join(" "), s = this.getColorStyle(), i = {
39
+ ...s ? { color: s } : {},
40
+ ...this.sx
41
+ };
42
+ return m`
43
+ <${r} part="text" class=${o} style=${h(i)}>
44
+ <slot></slot>
45
+ </${r}>
46
+ `;
47
+ }
48
+ };
49
+ t.styles = [
50
+ y,
51
+ p`
52
+ :host {
53
+ display: contents;
54
+ }
55
+
56
+ .text {
57
+ margin: 0;
58
+ padding: 0;
59
+ font-family: var(--font-body);
60
+ line-height: 1.4;
61
+ color: var(--ink-black);
62
+ }
63
+
64
+ /* Size variants using design-tokens */
65
+ .text--sm {
66
+ font-size: var(--font-size-sm);
67
+ }
68
+ .text--base {
69
+ font-size: var(--font-size-base);
70
+ }
71
+ .text--lg {
72
+ font-size: var(--font-size-lg);
73
+ }
74
+ .text--xl {
75
+ font-size: var(--font-size-xl);
76
+ }
77
+ .text--2xl {
78
+ font-size: var(--font-size-2xl);
79
+ }
80
+
81
+ /* Weight variants */
82
+ .text--w400 {
83
+ font-weight: 400;
84
+ }
85
+ .text--w500 {
86
+ font-weight: 500;
87
+ }
88
+ .text--w600 {
89
+ font-weight: 600;
90
+ }
91
+ .text--w700 {
92
+ font-weight: 700;
93
+ }
94
+
95
+ /* Color variants using design-tokens - these will respond to theme changes */
96
+ .text--primary {
97
+ color: var(--ink-black);
98
+ }
99
+ .text--secondary {
100
+ color: var(--ink-dark);
101
+ }
102
+ .text--tertiary {
103
+ color: var(--ink-medium);
104
+ }
105
+ .text--muted {
106
+ color: var(--ink-light);
107
+ }
108
+ .text--accent {
109
+ color: var(--accent-primary);
110
+ }
111
+ .text--success {
112
+ color: var(--accent-success);
113
+ }
114
+ .text--error {
115
+ color: var(--error-base);
116
+ }
117
+ .text--warning {
118
+ color: var(--semantic-warning);
119
+ }
120
+ .text--info {
121
+ color: var(--semantic-info);
122
+ }
123
+ `
124
+ ];
125
+ n([
126
+ a({ type: String })
127
+ ], t.prototype, "tag", 2);
128
+ n([
129
+ a({ type: String })
130
+ ], t.prototype, "size", 2);
131
+ n([
132
+ a({ type: String })
133
+ ], t.prototype, "weight", 2);
134
+ n([
135
+ a({ type: String })
136
+ ], t.prototype, "color", 2);
137
+ n([
138
+ a({ type: Object })
139
+ ], t.prototype, "sx", 2);
140
+ t = n([
141
+ g("tc-text")
142
+ ], t);
143
+ export {
144
+ t as TcText
145
+ };