create-nativecore 0.1.1 → 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.
Files changed (175) hide show
  1. package/README.md +6 -14
  2. package/bin/index.mjs +403 -431
  3. package/package.json +3 -2
  4. package/template/.env.example +28 -0
  5. package/template/.htmlhintrc +14 -0
  6. package/template/api/data/dashboard.json +11 -0
  7. package/template/api/data/users.json +18 -0
  8. package/template/api/mockApi.js +161 -0
  9. package/template/assets/icon.svg +13 -0
  10. package/template/assets/logo.svg +25 -0
  11. package/template/eslint.config.js +94 -0
  12. package/template/index.html +137 -0
  13. package/template/manifest.json +19 -0
  14. package/template/public/.well-known/security.txt +9 -0
  15. package/template/public/_headers +24 -0
  16. package/template/public/_redirects +14 -0
  17. package/template/public/assets/icon.svg +13 -0
  18. package/template/public/assets/logo.svg +25 -0
  19. package/template/public/manifest.json +19 -0
  20. package/template/public/robots.txt +13 -0
  21. package/template/public/sitemap.xml +27 -0
  22. package/template/scripts/build-for-bots.mjs +121 -0
  23. package/template/scripts/convert-to-ts.mjs +106 -0
  24. package/template/scripts/fix-encoding.mjs +38 -0
  25. package/template/scripts/fix-svg-paths.mjs +32 -0
  26. package/template/scripts/generate-cf-router.mjs +52 -0
  27. package/template/scripts/inject-dev-tools.mjs +41 -0
  28. package/template/scripts/inject-version.mjs +65 -0
  29. package/template/scripts/make-component.mjs +445 -0
  30. package/template/scripts/make-component.mjs.backup +432 -0
  31. package/template/scripts/make-controller.mjs +119 -0
  32. package/template/scripts/make-core-component.mjs +303 -0
  33. package/template/scripts/make-view.mjs +346 -0
  34. package/template/scripts/minify.mjs +71 -0
  35. package/template/scripts/prepare-static-assets.mjs +141 -0
  36. package/template/scripts/prompt-bot-build.mjs +223 -0
  37. package/template/scripts/remove-component.mjs +170 -0
  38. package/template/scripts/remove-core-component.mjs +156 -0
  39. package/template/scripts/remove-dev.mjs +13 -0
  40. package/template/scripts/remove-view.mjs +200 -0
  41. package/template/scripts/strip-dev-blocks.mjs +30 -0
  42. package/template/scripts/watch-compile.mjs +69 -0
  43. package/template/server.js +1066 -0
  44. package/template/src/app.ts +115 -0
  45. package/template/src/components/appRegistry.ts +8 -0
  46. package/template/src/components/core/app-footer.ts +27 -0
  47. package/template/src/components/core/app-header.ts +175 -0
  48. package/template/src/components/core/app-sidebar.ts +238 -0
  49. package/template/src/components/core/loading-spinner.ts +25 -0
  50. package/template/src/components/core/nc-a.ts +313 -0
  51. package/template/src/components/core/nc-accordion.ts +186 -0
  52. package/template/src/components/core/nc-alert.ts +153 -0
  53. package/template/src/components/core/nc-animation.ts +1150 -0
  54. package/template/src/components/core/nc-autocomplete.ts +271 -0
  55. package/template/src/components/core/nc-avatar-group.ts +113 -0
  56. package/template/src/components/core/nc-avatar.ts +148 -0
  57. package/template/src/components/core/nc-badge.ts +86 -0
  58. package/template/src/components/core/nc-bottom-nav.ts +214 -0
  59. package/template/src/components/core/nc-breadcrumb.ts +96 -0
  60. package/template/src/components/core/nc-button.ts +307 -0
  61. package/template/src/components/core/nc-card.ts +160 -0
  62. package/template/src/components/core/nc-checkbox.ts +282 -0
  63. package/template/src/components/core/nc-chip.ts +115 -0
  64. package/template/src/components/core/nc-code.ts +314 -0
  65. package/template/src/components/core/nc-collapsible.ts +154 -0
  66. package/template/src/components/core/nc-color-picker.ts +268 -0
  67. package/template/src/components/core/nc-copy-button.ts +119 -0
  68. package/template/src/components/core/nc-date-picker.ts +443 -0
  69. package/template/src/components/core/nc-div.ts +280 -0
  70. package/template/src/components/core/nc-divider.ts +81 -0
  71. package/template/src/components/core/nc-drawer.ts +230 -0
  72. package/template/src/components/core/nc-dropdown.ts +178 -0
  73. package/template/src/components/core/nc-empty-state.ts +134 -0
  74. package/template/src/components/core/nc-file-upload.ts +354 -0
  75. package/template/src/components/core/nc-form.ts +312 -0
  76. package/template/src/components/core/nc-image.ts +184 -0
  77. package/template/src/components/core/nc-input.ts +383 -0
  78. package/template/src/components/core/nc-kbd.ts +48 -0
  79. package/template/src/components/core/nc-menu-item.ts +193 -0
  80. package/template/src/components/core/nc-menu.ts +376 -0
  81. package/template/src/components/core/nc-modal.ts +238 -0
  82. package/template/src/components/core/nc-nav-item.ts +151 -0
  83. package/template/src/components/core/nc-number-input.ts +350 -0
  84. package/template/src/components/core/nc-otp-input.ts +235 -0
  85. package/template/src/components/core/nc-pagination.ts +178 -0
  86. package/template/src/components/core/nc-popover.ts +260 -0
  87. package/template/src/components/core/nc-progress-circular.ts +119 -0
  88. package/template/src/components/core/nc-progress.ts +134 -0
  89. package/template/src/components/core/nc-radio.ts +235 -0
  90. package/template/src/components/core/nc-rating.ts +266 -0
  91. package/template/src/components/core/nc-rich-text.ts +283 -0
  92. package/template/src/components/core/nc-scroll-top.ts +116 -0
  93. package/template/src/components/core/nc-select.ts +452 -0
  94. package/template/src/components/core/nc-skeleton.ts +107 -0
  95. package/template/src/components/core/nc-slider.ts +285 -0
  96. package/template/src/components/core/nc-snackbar.ts +230 -0
  97. package/template/src/components/core/nc-splash.ts +343 -0
  98. package/template/src/components/core/nc-stepper.ts +247 -0
  99. package/template/src/components/core/nc-switch.ts +281 -0
  100. package/template/src/components/core/nc-tab-item.ts +138 -0
  101. package/template/src/components/core/nc-table.ts +279 -0
  102. package/template/src/components/core/nc-tabs.ts +554 -0
  103. package/template/src/components/core/nc-tag-input.ts +279 -0
  104. package/template/src/components/core/nc-textarea.ts +216 -0
  105. package/template/src/components/core/nc-time-picker.ts +438 -0
  106. package/template/src/components/core/nc-timeline.ts +186 -0
  107. package/template/src/components/core/nc-tooltip.ts +143 -0
  108. package/template/src/components/frameworkRegistry.ts +68 -0
  109. package/template/src/components/preloadRegistry.ts +28 -0
  110. package/template/src/components/registry.ts +8 -0
  111. package/template/src/components/ui/dashboard-signal-lab.ts +284 -0
  112. package/template/src/constants/apiEndpoints.ts +27 -0
  113. package/template/src/constants/errorMessages.ts +23 -0
  114. package/template/src/constants/index.ts +8 -0
  115. package/template/src/constants/routePaths.ts +15 -0
  116. package/template/src/constants/storageKeys.ts +18 -0
  117. package/template/src/controllers/dashboard.controller.ts +200 -0
  118. package/template/src/controllers/home.controller.ts +21 -0
  119. package/template/src/controllers/index.ts +11 -0
  120. package/template/src/controllers/login.controller.ts +131 -0
  121. package/template/src/core/component.ts +354 -0
  122. package/template/src/core/errorHandler.ts +85 -0
  123. package/template/src/core/gpu-animation.ts +604 -0
  124. package/template/src/core/http.ts +173 -0
  125. package/template/src/core/lazyComponents.ts +90 -0
  126. package/template/src/core/router.ts +653 -0
  127. package/template/src/core/signals.ts +146 -0
  128. package/template/src/core/state.ts +248 -0
  129. package/template/src/dev/component-editor.ts +1363 -0
  130. package/template/src/dev/component-overlay.ts +278 -0
  131. package/template/src/dev/context-menu.ts +223 -0
  132. package/template/src/dev/denc-tools.ts +250 -0
  133. package/template/src/dev/hmr.ts +189 -0
  134. package/template/src/dev/nfbs.code-workspace +27 -0
  135. package/template/src/dev/outline-panel.ts +1247 -0
  136. package/template/src/middleware/auth.middleware.ts +23 -0
  137. package/template/src/routes/routes.ts +38 -0
  138. package/template/src/services/api.service.ts +394 -0
  139. package/template/src/services/auth.service.ts +176 -0
  140. package/template/src/services/index.ts +8 -0
  141. package/template/src/services/logger.service.ts +74 -0
  142. package/template/src/services/storage.service.ts +88 -0
  143. package/template/src/stores/appStore.ts +57 -0
  144. package/template/src/stores/uiStore.ts +36 -0
  145. package/template/src/styles/core-variables.css +219 -0
  146. package/template/src/styles/core.css +710 -0
  147. package/template/src/styles/main.css +3164 -0
  148. package/template/src/styles/variables.css +152 -0
  149. package/template/src/types/global.d.ts +47 -0
  150. package/template/src/utils/cacheBuster.ts +20 -0
  151. package/template/src/utils/dom.ts +149 -0
  152. package/template/src/utils/events.ts +203 -0
  153. package/template/src/utils/form.ts +176 -0
  154. package/template/src/utils/formatters.ts +169 -0
  155. package/template/src/utils/helpers.ts +195 -0
  156. package/template/src/utils/markdown.ts +307 -0
  157. package/template/src/utils/sidebar.ts +96 -0
  158. package/template/src/utils/smoothScroll.ts +85 -0
  159. package/template/src/utils/templates.ts +23 -0
  160. package/template/src/utils/validation.ts +73 -0
  161. package/template/src/views/protected/dashboard.html +293 -0
  162. package/template/src/views/public/home.html +150 -0
  163. package/template/src/views/public/login.html +102 -0
  164. package/template/tests/unit/component.test.ts +87 -0
  165. package/template/tests/unit/computed.test.ts +79 -0
  166. package/template/tests/unit/form.test.ts +68 -0
  167. package/template/tests/unit/formatters.test.ts +49 -0
  168. package/template/tests/unit/lazy-components.test.ts +59 -0
  169. package/template/tests/unit/markdown.test.ts +62 -0
  170. package/template/tests/unit/router.test.ts +112 -0
  171. package/template/tests/unit/signals.test.ts +54 -0
  172. package/template/tests/unit/validation.test.ts +50 -0
  173. package/template/tsconfig.build.json +21 -0
  174. package/template/tsconfig.json +51 -0
  175. package/template/vitest.config.ts +36 -0
@@ -0,0 +1,160 @@
1
+ /**
2
+ * NcCard Component
3
+ *
4
+ * NativeCore Framework Core Component
5
+ * Generated on 2/1/2026
6
+ *
7
+ * ⚠️ FRAMEWORK INTERNAL COMPONENT ⚠️
8
+ * This component uses --nc- CSS variables from core-variables.css
9
+ * for consistent styling across the framework.
10
+ *
11
+ * ═══════════════════════════════════════════════════════════════════
12
+ * DEV TOOLS INTEGRATION - How to make attributes editable in sidebar:
13
+ * ═══════════════════════════════════════════════════════════════════
14
+ *
15
+ * 1. ADD TO observedAttributes:
16
+ * static get observedAttributes() {
17
+ * return ['variant', 'size', 'disabled']; // ← These become editable
18
+ * }
19
+ *
20
+ * 2. USE getAttribute() IN template():
21
+ * const variant = this.getAttribute('variant') || 'primary';
22
+ * const size = this.getAttribute('size') || 'md';
23
+ *
24
+ * 3. FOR DROPDOWN SELECTORS (variant/size):
25
+ * Name attributes 'variant' or 'size' AND use CSS patterns:
26
+ *
27
+ * Option A - :host() selectors (RECOMMENDED for core components):
28
+ * :host([variant="primary"]) { ... }
29
+ * :host([variant="secondary"]) { ... }
30
+ * :host([size="sm"]) { ... }
31
+ * :host([size="lg"]) { ... }
32
+ *
33
+ * Option B - Class selectors:
34
+ * .primary { ... }
35
+ * .secondary { ... }
36
+ * .btn-sm { ... }
37
+ * .btn-lg { ... }
38
+ *
39
+ * The dev tools will auto-detect these patterns and create dropdowns!
40
+ *
41
+ * 4. ATTRIBUTE TYPES (auto-detected):
42
+ * - Boolean: disabled, loading, hidden, readonly → Checkbox
43
+ * - Variant/Size: variant, size (with CSS) → Dropdown
44
+ * - Number: count, max, min, step → Slider
45
+ * - Everything else → Text input
46
+ *
47
+ * 5. LIVE UPDATES:
48
+ * Implement attributeChangedCallback for instant preview updates
49
+ *
50
+ * ═══════════════════════════════════════════════════════════════════
51
+ *
52
+ * Usage:
53
+ *
54
+ *
55
+ *
56
+ * Attributes:
57
+ * - variant: Component style variant
58
+ * - size: Component size (sm, md, lg)
59
+ * - disabled: Disabled state
60
+ */
61
+
62
+ import { Component, defineComponent } from '@core/component.js';
63
+
64
+ export class NcCard extends Component {
65
+ static useShadowDOM = true;
66
+
67
+ // ═══ Define dropdown options for dev tools (auto-detected) ═══
68
+ static attributeOptions = {
69
+ variant: ['primary', 'secondary', 'success', 'danger'],
70
+ size: ['sm', 'md', 'lg']
71
+ };
72
+
73
+ // ═══ Attributes listed here become editable in dev tools sidebar ═══
74
+ static get observedAttributes() {
75
+ return ['variant', 'size', 'disabled'];
76
+ }
77
+
78
+ constructor() {
79
+ super();
80
+ }
81
+
82
+ template() {
83
+ return `
84
+ <style>
85
+ :host {
86
+ display: block;
87
+ font-family: var(--nc-font-family);
88
+ padding: var(--nc-spacing-md);
89
+ border-radius: var(--nc-radius-md);
90
+ transition: all var(--nc-transition-fast);
91
+ width: 100%;
92
+ box-sizing: border-box;
93
+ }
94
+
95
+ /* ═══ Variant Options (auto-detected for dropdown) ═══ */
96
+ /* Dev tools will scan :host([variant="..."]) patterns */
97
+
98
+ :host([variant="primary"]) {
99
+ background: var(--nc-gradient-primary);
100
+ color: var(--nc-white);
101
+ }
102
+
103
+ :host([variant="secondary"]) {
104
+ background: var(--nc-bg-secondary);
105
+ color: var(--nc-text);
106
+ border: 1px solid var(--nc-border);
107
+ }
108
+
109
+ :host([variant="success"]) {
110
+ background: var(--nc-gradient-success);
111
+ color: var(--nc-white);
112
+ }
113
+
114
+ :host([variant="danger"]) {
115
+ background: var(--nc-gradient-danger);
116
+ color: var(--nc-white);
117
+ }
118
+
119
+ /* ═══ Size Options (auto-detected for dropdown) ═══ */
120
+ /* Dev tools will scan :host([size="..."]) patterns */
121
+
122
+ :host([size="sm"]) {
123
+ padding: var(--nc-spacing-sm);
124
+ font-size: var(--nc-font-size-sm);
125
+ }
126
+
127
+ :host([size="md"]) {
128
+ padding: var(--nc-spacing-md);
129
+ font-size: var(--nc-font-size-base);
130
+ }
131
+
132
+ :host([size="lg"]) {
133
+ padding: var(--nc-spacing-lg);
134
+ font-size: var(--nc-font-size-lg);
135
+ }
136
+
137
+ /* ═══ Disabled State (auto-detected as checkbox) ═══ */
138
+ :host([disabled]) {
139
+ opacity: 0.5;
140
+ pointer-events: none;
141
+ }
142
+ </style>
143
+
144
+ <slot></slot>
145
+ `;
146
+ }
147
+
148
+ onMount() {
149
+ // Component logic here
150
+ }
151
+
152
+ // ═══ Makes changes instant in dev tools preview ═══
153
+ attributeChangedCallback(name: string, oldValue: string, newValue: string) {
154
+ if (oldValue !== newValue && this._mounted) {
155
+ this.render();
156
+ }
157
+ }
158
+ }
159
+
160
+ defineComponent('nc-card', NcCard);
@@ -0,0 +1,282 @@
1
+ /**
2
+ * NcCheckbox Component
3
+ *
4
+ * NativeCore Framework Core Component
5
+ *
6
+ * Attributes:
7
+ * - label: string — text label shown next to the checkbox
8
+ * - name: string — form field name
9
+ * - value: string — value submitted with a form (default: 'on')
10
+ * - checked: boolean — checked state
11
+ * - disabled: boolean — disabled state
12
+ * - size: 'sm' | 'md' | 'lg' (default: 'md')
13
+ * - variant: 'primary' | 'success' | 'danger' (default: 'primary')
14
+ * - indeterminate: boolean — indeterminate visual state
15
+ *
16
+ * Events:
17
+ * - change: CustomEvent<{ checked: boolean; value: string; name: string }>
18
+ *
19
+ * Usage:
20
+ * <nc-checkbox label="Accept terms" name="terms" checked></nc-checkbox>
21
+ * <nc-checkbox label="Disabled" disabled></nc-checkbox>
22
+ * <nc-checkbox label="Danger" variant="danger"></nc-checkbox>
23
+ */
24
+
25
+ import { Component, defineComponent } from '@core/component.js';
26
+
27
+ export class NcCheckbox extends Component {
28
+ static useShadowDOM = true;
29
+
30
+ private readonly _handleInputChange = (event: Event) => {
31
+ const target = event.target as HTMLInputElement | null;
32
+ if (!target || target.type !== 'checkbox') return;
33
+ this._setCheckedState(target.checked);
34
+ };
35
+
36
+ private readonly _handleKeyDown = (e: KeyboardEvent) => {
37
+ if (e.key === ' ' || e.key === 'Enter') {
38
+ e.preventDefault();
39
+ if (!this.hasAttribute('disabled')) {
40
+ this._setCheckedState(!this.hasAttribute('checked'));
41
+ }
42
+ }
43
+ };
44
+
45
+ static attributeOptions = {
46
+ variant: ['primary', 'success', 'danger'],
47
+ size: ['sm', 'md', 'lg']
48
+ };
49
+
50
+ static get observedAttributes() {
51
+ return ['label', 'name', 'value', 'checked', 'disabled', 'size', 'variant', 'indeterminate'];
52
+ }
53
+
54
+ constructor() {
55
+ super();
56
+ }
57
+
58
+ template() {
59
+ const label = this.getAttribute('label') || '';
60
+ const size = this.getAttribute('size') || 'md';
61
+ const checked = this.hasAttribute('checked');
62
+ const disabled = this.hasAttribute('disabled');
63
+
64
+ return `
65
+ <style>
66
+ :host {
67
+ display: inline-flex;
68
+ align-items: center;
69
+ gap: var(--nc-spacing-sm);
70
+ cursor: ${disabled ? 'not-allowed' : 'pointer'};
71
+ user-select: none;
72
+ font-family: var(--nc-font-family);
73
+ opacity: ${disabled ? '0.5' : '1'};
74
+ }
75
+
76
+ .checkbox-wrapper {
77
+ display: inline-flex;
78
+ align-items: center;
79
+ gap: var(--nc-spacing-sm);
80
+ }
81
+
82
+ /* Hidden native input — keeps form semantics */
83
+ input[type="checkbox"] {
84
+ position: absolute;
85
+ opacity: 0;
86
+ width: 0;
87
+ height: 0;
88
+ pointer-events: none;
89
+ }
90
+
91
+ .box {
92
+ display: inline-flex;
93
+ align-items: center;
94
+ justify-content: center;
95
+ flex-shrink: 0;
96
+ border-radius: var(--nc-radius-sm);
97
+ border: 2px solid var(--nc-border-dark);
98
+ background: var(--nc-bg);
99
+ transition: all var(--nc-transition-fast);
100
+ position: relative;
101
+ box-sizing: border-box;
102
+ }
103
+
104
+ /* Size variants */
105
+ :host([size="sm"]) .box,
106
+ :host(:not([size])) .box {
107
+ width: 16px;
108
+ height: 16px;
109
+ }
110
+
111
+ :host([size="md"]) .box {
112
+ width: 20px;
113
+ height: 20px;
114
+ }
115
+
116
+ :host([size="lg"]) .box {
117
+ width: 24px;
118
+ height: 24px;
119
+ }
120
+
121
+ /* Default size (md) */
122
+ .box {
123
+ width: 20px;
124
+ height: 20px;
125
+ }
126
+
127
+ /* Checked state — variant colors */
128
+ :host([checked]) .box,
129
+ :host([indeterminate]) .box {
130
+ border-color: var(--nc-primary);
131
+ background: var(--nc-primary);
132
+ }
133
+
134
+ :host([variant="success"][checked]) .box,
135
+ :host([variant="success"][indeterminate]) .box {
136
+ border-color: var(--nc-success);
137
+ background: var(--nc-success);
138
+ }
139
+
140
+ :host([variant="danger"][checked]) .box,
141
+ :host([variant="danger"][indeterminate]) .box {
142
+ border-color: var(--nc-danger);
143
+ background: var(--nc-danger);
144
+ }
145
+
146
+ /* Checkmark SVG */
147
+ .check-icon {
148
+ display: none;
149
+ pointer-events: none;
150
+ }
151
+
152
+ :host([checked]) .check-icon {
153
+ display: block;
154
+ }
155
+
156
+ /* Indeterminate dash */
157
+ .indeterminate-icon {
158
+ display: none;
159
+ pointer-events: none;
160
+ }
161
+
162
+ :host([indeterminate]:not([checked])) .indeterminate-icon {
163
+ display: block;
164
+ }
165
+
166
+ :host([indeterminate]:not([checked])) .check-icon {
167
+ display: none;
168
+ }
169
+
170
+ /* Hover */
171
+ :host(:not([disabled])) .box:hover {
172
+ border-color: var(--nc-primary);
173
+ box-shadow: 0 0 0 3px rgba(16, 185, 129, 0.15);
174
+ }
175
+
176
+ :host([variant="success"]:not([disabled])) .box:hover {
177
+ border-color: var(--nc-success);
178
+ box-shadow: 0 0 0 3px rgba(16, 185, 129, 0.15);
179
+ }
180
+
181
+ :host([variant="danger"]:not([disabled])) .box:hover {
182
+ border-color: var(--nc-danger);
183
+ box-shadow: 0 0 0 3px rgba(239, 68, 68, 0.15);
184
+ }
185
+
186
+ /* Focus ring */
187
+ :host(:focus-visible) .box {
188
+ outline: 2px solid var(--nc-primary);
189
+ outline-offset: 2px;
190
+ }
191
+
192
+ /* Label */
193
+ .label {
194
+ font-size: var(--nc-font-size-base);
195
+ color: var(--nc-text);
196
+ line-height: var(--nc-line-height-normal);
197
+ }
198
+
199
+ :host([size="sm"]) .label {
200
+ font-size: var(--nc-font-size-sm);
201
+ }
202
+
203
+ :host([size="lg"]) .label {
204
+ font-size: var(--nc-font-size-lg);
205
+ }
206
+ </style>
207
+
208
+ <label class="checkbox-wrapper">
209
+ <input
210
+ type="checkbox"
211
+ ${checked ? 'checked' : ''}
212
+ ${disabled ? 'disabled' : ''}
213
+ name="${this.getAttribute('name') || ''}"
214
+ value="${this.getAttribute('value') || 'on'}"
215
+ />
216
+ <span class="box">
217
+ <svg class="check-icon" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 12 12" fill="none"
218
+ width="${size === 'sm' ? '8' : size === 'lg' ? '14' : '11'}"
219
+ height="${size === 'sm' ? '8' : size === 'lg' ? '14' : '11'}">
220
+ <path d="M2 6l3 3 5-5" stroke="white" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"/>
221
+ </svg>
222
+ <svg class="indeterminate-icon" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 12 12" fill="none"
223
+ width="${size === 'sm' ? '8' : size === 'lg' ? '14' : '11'}"
224
+ height="${size === 'sm' ? '8' : size === 'lg' ? '14' : '11'}">
225
+ <path d="M2 6h8" stroke="white" stroke-width="2" stroke-linecap="round"/>
226
+ </svg>
227
+ </span>
228
+ ${label ? `<span class="label">${label}</span>` : '<slot></slot>'}
229
+ </label>
230
+ `;
231
+ }
232
+
233
+ onMount() {
234
+ if (!this.hasAttribute('tabindex')) {
235
+ this.setAttribute('tabindex', '0');
236
+ }
237
+ this.setAttribute('role', 'checkbox');
238
+ this.setAttribute('aria-checked', String(this.hasAttribute('checked')));
239
+
240
+ this.shadowRoot!.addEventListener('change', this._handleInputChange);
241
+ this.addEventListener('keydown', this._handleKeyDown);
242
+ }
243
+
244
+ onUnmount() {
245
+ this.shadowRoot?.removeEventListener('change', this._handleInputChange);
246
+ this.removeEventListener('keydown', this._handleKeyDown);
247
+ }
248
+
249
+ private _setCheckedState(isChecked: boolean) {
250
+ if (isChecked) {
251
+ this.setAttribute('checked', '');
252
+ this.removeAttribute('indeterminate');
253
+ } else {
254
+ this.removeAttribute('checked');
255
+ }
256
+
257
+ this.setAttribute('aria-checked', String(this.hasAttribute('checked')));
258
+
259
+ this.dispatchEvent(new CustomEvent('change', {
260
+ bubbles: true,
261
+ composed: true,
262
+ detail: {
263
+ checked: this.hasAttribute('checked'),
264
+ value: this.getAttribute('value') || 'on',
265
+ name: this.getAttribute('name') || ''
266
+ }
267
+ }));
268
+ }
269
+
270
+ attributeChangedCallback(name: string, oldValue: string, newValue: string) {
271
+ if (oldValue !== newValue) {
272
+ this.render();
273
+ if (name === 'checked' || name === 'indeterminate') {
274
+ this.setAttribute('aria-checked',
275
+ this.hasAttribute('indeterminate') ? 'mixed' : String(this.hasAttribute('checked'))
276
+ );
277
+ }
278
+ }
279
+ }
280
+ }
281
+
282
+ defineComponent('nc-checkbox', NcCheckbox);
@@ -0,0 +1,115 @@
1
+ /**
2
+ * NcChip Component
3
+ *
4
+ * Attributes:
5
+ * - variant: 'default'|'primary'|'success'|'warning'|'danger'|'neutral' (default: 'default')
6
+ * - size: 'sm'|'md'|'lg' (default: 'md')
7
+ * - dismissible: boolean — shows an × button; fires 'dismiss' event on click
8
+ * - disabled: boolean
9
+ * - icon: string — URL/path to a leading icon image
10
+ *
11
+ * Events:
12
+ * - dismiss: CustomEvent (when × is clicked)
13
+ *
14
+ * Usage:
15
+ * <nc-chip>React</nc-chip>
16
+ * <nc-chip variant="success" dismissible>Published</nc-chip>
17
+ */
18
+
19
+ import { Component, defineComponent } from '@core/component.js';
20
+
21
+ export class NcChip extends Component {
22
+ static useShadowDOM = true;
23
+
24
+ static get observedAttributes() {
25
+ return ['variant', 'size', 'dismissible', 'disabled', 'icon'];
26
+ }
27
+
28
+ template() {
29
+ const variant = this.getAttribute('variant') || 'default';
30
+ const dismissible = this.hasAttribute('dismissible');
31
+ const disabled = this.hasAttribute('disabled');
32
+ const icon = this.getAttribute('icon');
33
+
34
+ return `
35
+ <style>
36
+ :host { display: inline-flex; }
37
+
38
+ .chip {
39
+ display: inline-flex;
40
+ align-items: center;
41
+ gap: var(--nc-spacing-xs);
42
+ border-radius: 999px;
43
+ font-family: var(--nc-font-family);
44
+ font-weight: var(--nc-font-weight-medium);
45
+ white-space: nowrap;
46
+ border: 1px solid transparent;
47
+ transition: opacity var(--nc-transition-fast);
48
+ opacity: ${disabled ? '0.5' : '1'};
49
+ pointer-events: ${disabled ? 'none' : 'auto'};
50
+ }
51
+
52
+ :host([size="sm"]) .chip { font-size: var(--nc-font-size-xs); padding: 2px 8px; }
53
+ :host([size="lg"]) .chip { font-size: var(--nc-font-size-base); padding: 6px 14px; }
54
+ .chip { font-size: var(--nc-font-size-sm); padding: 3px 10px; }
55
+
56
+ /* Variants */
57
+ .chip--default { background: var(--nc-bg-secondary); color: var(--nc-text); border-color: var(--nc-border); }
58
+ .chip--primary { background: rgba(16,185,129,.12); color: var(--nc-primary); border-color: var(--nc-primary); }
59
+ .chip--success { background: rgba(16,185,129,.12); color: var(--nc-success, #10b981); border-color: var(--nc-success, #10b981); }
60
+ .chip--warning { background: rgba(245,158,11,.12); color: var(--nc-warning, #f59e0b); border-color: var(--nc-warning, #f59e0b); }
61
+ .chip--danger { background: rgba(239,68,68,.10); color: var(--nc-danger, #ef4444); border-color: var(--nc-danger, #ef4444); }
62
+ .chip--neutral { background: var(--nc-bg-tertiary); color: var(--nc-text-muted); border-color: var(--nc-border-dark); }
63
+
64
+ .chip__icon { width: 14px; height: 14px; border-radius: 50%; object-fit: cover; }
65
+
66
+ .chip__dismiss {
67
+ display: inline-flex;
68
+ align-items: center;
69
+ justify-content: center;
70
+ background: none;
71
+ border: none;
72
+ cursor: pointer;
73
+ padding: 0;
74
+ margin-left: 2px;
75
+ color: inherit;
76
+ opacity: 0.6;
77
+ transition: opacity var(--nc-transition-fast);
78
+ line-height: 1;
79
+ }
80
+ .chip__dismiss:hover { opacity: 1; }
81
+
82
+ ::slotted(*) { pointer-events: none; }
83
+ </style>
84
+ <span class="chip chip--${variant}">
85
+ ${icon ? `<img class="chip__icon" src="${icon}" alt="" aria-hidden="true" />` : ''}
86
+ <slot></slot>
87
+ ${dismissible ? `
88
+ <button class="chip__dismiss" type="button" aria-label="Remove">
89
+ <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 12 12" fill="none" width="10" height="10">
90
+ <path d="M2 2l8 8M10 2l-8 8" stroke="currentColor" stroke-width="1.5" stroke-linecap="round"/>
91
+ </svg>
92
+ </button>` : ''}
93
+ </span>
94
+ `;
95
+ }
96
+
97
+ onMount() {
98
+ const btn = this.$<HTMLButtonElement>('.chip__dismiss');
99
+ if (btn) {
100
+ btn.addEventListener('click', (e) => {
101
+ e.stopPropagation();
102
+ this.dispatchEvent(new CustomEvent('dismiss', { bubbles: true, composed: true }));
103
+ });
104
+ }
105
+ }
106
+
107
+ attributeChangedCallback(name: string, oldValue: string, newValue: string) {
108
+ if (oldValue !== newValue && this._mounted) {
109
+ this.render();
110
+ this.onMount();
111
+ }
112
+ }
113
+ }
114
+
115
+ defineComponent('nc-chip', NcChip);