@diniz/webcomponents 1.0.3 → 1.0.5

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -175,8 +175,35 @@ import '@diniz/webcomponents/dist/style.css';
175
175
  --radius-lg: 0.5rem;
176
176
  }
177
177
  ```
178
+ **Update `src/main.ts`:**
179
+ ```typescript
180
+ import '@diniz/webcomponents';
181
+ import '@diniz/webcomponents/dist/style.css';
178
182
 
179
- ## Quick Start
183
+ document.querySelector<HTMLDivElement>('#app')!.innerHTML = `
184
+ <div>
185
+ <h1>My Web Components App</h1>
186
+ <ui-button variant="primary">Click Me</ui-button>
187
+ <ui-date-picker format="DD/MM/YYYY"></ui-date-picker>
188
+ <ui-table id="myTable"></ui-table>
189
+ </div>
190
+ `;
191
+
192
+ // Add some data to the table
193
+ const table = document.getElementById('myTable') as any;
194
+ table.data = {
195
+ columns: [
196
+ { key: 'name', label: 'Name' },
197
+ { key: 'role', label: 'Role' }
198
+ ],
199
+ rows: [
200
+ { name: 'Alice', role: 'Admin' },
201
+ { name: 'Bob', role: 'User' }
202
+ ]
203
+ };
204
+ ```
205
+
206
+ ### Using via CDN or Direct Import
180
207
 
181
208
  ```html
182
209
  <script type="module">
@@ -708,6 +735,105 @@ store.subscribe(state => {
708
735
  });
709
736
  ```
710
737
 
738
+ ### HTTP Client
739
+
740
+ Lightweight HTTP client with interceptor support for API requests:
741
+
742
+ ```typescript
743
+ import { http } from '@diniz/webcomponents';
744
+
745
+ // Set base URL for all requests
746
+ http.setBaseURL('https://api.example.com');
747
+
748
+ // Set default headers
749
+ http.setDefaultHeaders({ 'Authorization': 'Bearer token' });
750
+
751
+ // Make requests
752
+ const users = await http.get<User[]>('/users');
753
+ const newUser = await http.post<User>('/users', { name: 'Alice' });
754
+ await http.put(`/users/${id}`, updatedData);
755
+ await http.delete(`/users/${id}`);
756
+ ```
757
+
758
+ **Request Interceptors:**
759
+
760
+ ```typescript
761
+ // Add auth token to every request
762
+ http.interceptors.request.use((config) => {
763
+ const token = localStorage.getItem('auth_token');
764
+ if (token) {
765
+ config.headers = config.headers || {};
766
+ config.headers['Authorization'] = `Bearer ${token}`;
767
+ }
768
+ return config;
769
+ });
770
+
771
+ // Handle request errors
772
+ http.interceptors.request.use(
773
+ (config) => config,
774
+ (error) => {
775
+ console.error('Request failed:', error);
776
+ throw error;
777
+ }
778
+ );
779
+ ```
780
+
781
+ **Response Interceptors:**
782
+
783
+ ```typescript
784
+ // Transform response data
785
+ http.interceptors.response.use((response) => {
786
+ // Unwrap API response if it's nested
787
+ if (response.data?.result) {
788
+ response.data = response.data.result;
789
+ }
790
+ return response;
791
+ });
792
+
793
+ // Handle errors globally
794
+ http.interceptors.response.use(
795
+ (response) => response,
796
+ (error) => {
797
+ if (error.response?.status === 401) {
798
+ // Handle unauthorized
799
+ localStorage.removeItem('auth_token');
800
+ window.location.href = '/login';
801
+ }
802
+ throw error;
803
+ }
804
+ );
805
+ ```
806
+
807
+ **Methods:**
808
+
809
+ - `get<T>(url, config?)` - GET request
810
+ - `post<T>(url, data?, config?)` - POST request
811
+ - `put<T>(url, data?, config?)` - PUT request
812
+ - `patch<T>(url, data?, config?)` - PATCH request
813
+ - `delete<T>(url, config?)` - DELETE request
814
+ - `head<T>(url, config?)` - HEAD request
815
+
816
+ **Configuration:**
817
+
818
+ ```typescript
819
+ interface RequestConfig {
820
+ method?: string;
821
+ headers?: Record<string, string>;
822
+ body?: string | FormData | null;
823
+ timeout?: number; // Default: 30000ms
824
+ }
825
+ ```
826
+
827
+ **Features:**
828
+
829
+ - ✅ Request/response interceptors with error handling
830
+ - ✅ Automatic JSON serialization/deserialization
831
+ - ✅ Timeout support (default 30s)
832
+ - ✅ Global headers and base URL configuration
833
+ - ✅ FormData support for file uploads
834
+ - ✅ TypeScript generics for type-safe responses
835
+ - ✅ Automatic error messages with status codes
836
+
711
837
  ---
712
838
 
713
839
  ## Theming
@@ -779,215 +905,6 @@ src/
779
905
  └── styles/
780
906
  └── theme.css # Global theme variables
781
907
  ```
782
-
783
- ---
784
-
785
- ## Examples
786
-
787
- ### Form with Validation
788
-
789
- ```html
790
- <form id="myForm">
791
- <ui-input
792
- type="email"
793
- name="email"
794
- label="Email"
795
- required
796
- ></ui-input>
797
-
798
- <ui-input
799
- type="password"
800
- name="password"
801
- label="Password"
802
- minlength="8"
803
- required
804
- ></ui-input>
805
-
806
- <ui-button type="submit">Submit</ui-button>
807
- </form>
808
- ```
809
-
810
- ### Data Table with Pagination
811
-
812
- ```html
813
- <ui-table id="dataTable"></ui-table>
814
- <ui-pagination id="pagination" page-size="10"></ui-pagination>
815
-
816
- <script type="module">
817
- const table = document.getElementById('dataTable');
818
- const pagination = document.getElementById('pagination');
819
-
820
- async function loadData(page = 1) {
821
- const response = await fetch(`/api/data?page=${page}`);
822
- const data = await response.json();
823
-
824
- table.data = {
825
- columns: [
826
- { key: 'name', label: 'Name' },
827
- { key: 'email', label: 'Email' }
828
- ],
829
- rows: data.items
830
- };
831
-
832
- pagination.total = data.total;
833
- pagination.currentPage = page;
834
- }
835
-
836
- pagination.addEventListener('page-change', (e) => {
837
- loadData(e.detail.page);
838
- });
839
-
840
- loadData(1);
841
- </script>
842
- ```
843
-
844
- ### Date Range Picker
845
-
846
- ```html
847
- <ui-date-picker id="startDate" format="DD/MM/YYYY"></ui-date-picker>
848
- <ui-date-picker id="endDate" format="DD/MM/YYYY"></ui-date-picker>
849
-
850
- <script>
851
- const start = document.getElementById('startDate');
852
- const end = document.getElementById('endDate');
853
-
854
- start.addEventListener('date-change', (e) => {
855
- end.setAttribute('min', e.detail.value);
856
- });
857
-
858
- end.addEventListener('date-change', (e) => {
859
- start.setAttribute('max', e.detail.value);
860
- });
861
- </script>
862
- ```
863
-
864
- ### Confirmation Modal
865
-
866
- ```html
867
- <ui-button id="deleteBtn" variant="primary" icon="trash-2">
868
- Delete Item
869
- </ui-button>
870
-
871
- <ui-modal id="confirmModal" title="Confirm Delete" size="sm">
872
- <p>Are you sure you want to delete this item?</p>
873
- <p style="color: #ef4444;">This action cannot be undone.</p>
874
-
875
- <div slot="footer">
876
- <ui-button id="cancelBtn" variant="ghost">Cancel</ui-button>
877
- <ui-button id="confirmBtn" variant="primary">Delete</ui-button>
878
- </div>
879
- </ui-modal>
880
-
881
- <script>
882
- const deleteBtn = document.getElementById('deleteBtn');
883
- const modal = document.getElementById('confirmModal');
884
- const cancelBtn = document.getElementById('cancelBtn');
885
- const confirmBtn = document.getElementById('confirmBtn');
886
-
887
- deleteBtn.addEventListener('click', () => modal.open());
888
- cancelBtn.addEventListener('click', () => modal.close());
889
- confirmBtn.addEventListener('click', () => {
890
- // Perform delete action
891
- console.log('Item deleted');
892
- modal.close();
893
- });
894
- </script>
895
- ```
896
-
897
- ### Dynamic Form with Select
898
-
899
- ```html
900
- <form id="userForm">
901
- <ui-select
902
- id="roleSelect"
903
- label="User Role"
904
- placeholder="Select role..."
905
- ></ui-select>
906
-
907
- <ui-select
908
- id="countrySelect"
909
- label="Country"
910
- placeholder="Select country..."
911
- searchable
912
- ></ui-select>
913
-
914
- <ui-button type="submit" variant="primary" icon="check">
915
- Create User
916
- </ui-button>
917
- </form>
918
-
919
- <script>
920
- const roleSelect = document.getElementById('roleSelect');
921
- const countrySelect = document.getElementById('countrySelect');
922
-
923
- // Set options
924
- roleSelect.setAttribute('options', JSON.stringify([
925
- { value: 'admin', label: 'Administrator' },
926
- { value: 'user', label: 'User' },
927
- { value: 'guest', label: 'Guest' }
928
- ]));
929
-
930
- countrySelect.setAttribute('options', JSON.stringify([
931
- { value: 'us', label: 'United States' },
932
- { value: 'uk', label: 'United Kingdom' },
933
- { value: 'ca', label: 'Canada' }
934
- ]));
935
-
936
- document.getElementById('userForm').addEventListener('submit', (e) => {
937
- e.preventDefault();
938
- const role = roleSelect.getAttribute('value');
939
- const country = countrySelect.getAttribute('value');
940
- console.log({ role, country });
941
- });
942
- </script>
943
- ```
944
-
945
- ### Select All with Checkboxes
946
-
947
- ```html
948
- <ui-checkbox id="selectAll" label="Select All"></ui-checkbox>
949
-
950
- <div style="margin-left: 2rem;">
951
- <ui-checkbox class="item" label="Item 1" size="sm"></ui-checkbox>
952
- <ui-checkbox class="item" label="Item 2" size="sm"></ui-checkbox>
953
- <ui-checkbox class="item" label="Item 3" size="sm"></ui-checkbox>
954
- </div>
955
-
956
- <script>
957
- const selectAll = document.getElementById('selectAll');
958
- const items = document.querySelectorAll('.item');
959
-
960
- // Update select all based on items
961
- function updateSelectAll() {
962
- const checkedCount = Array.from(items).filter(
963
- item => item.hasAttribute('checked')
964
- ).length;
965
-
966
- if (checkedCount === 0) {
967
- selectAll.setChecked(false);
968
- } else if (checkedCount === items.length) {
969
- selectAll.setChecked(true);
970
- } else {
971
- selectAll.setIndeterminate(true);
972
- }
973
- }
974
-
975
- // Handle select all click
976
- selectAll.addEventListener('checkbox-change', (e) => {
977
- items.forEach(item => item.setChecked(e.detail.checked));
978
- });
979
-
980
- // Handle individual item clicks
981
- items.forEach(item => {
982
- item.addEventListener('checkbox-change', updateSelectAll);
983
- });
984
-
985
- updateSelectAll();
986
- </script>
987
- ```
988
-
989
- ---
990
-
991
908
  ## Contributing
992
909
 
993
910
  Contributions are welcome! Please feel free to submit a Pull Request.
@@ -0,0 +1,37 @@
1
+ var f=Object.defineProperty;var g=(r,e,o)=>e in r?f(r,e,{enumerable:!0,configurable:!0,writable:!0,value:o}):r[e]=o;var c=(r,e,o)=>g(r,typeof e!="symbol"?e+"":e,o);import{s as m}from"./index-DJpTIOwN.js";import{f as x}from"./vendor-BvJLUv9i.js";function v(r){let e=r;const o=new Set;return{get:()=>e,set:t=>{Object.is(e,t)||(e=t,o.forEach(a=>a(e)))},subscribe:t=>(o.add(t),()=>o.delete(t))}}class p extends HTMLElement{constructor(){super();c(this,"state");c(this,"signalUnsubs");this.attachShadow({mode:"open"}),this.state={},this.signalUnsubs=new Set}useSignal(o){const t=v(o),a=t.subscribe(()=>this.render());return this.signalUnsubs.add(a),t}setState(o){this.state={...this.state,...o},this.render()}connectedCallback(){this.render()}disconnectedCallback(){this.signalUnsubs.forEach(o=>o()),this.signalUnsubs.clear()}render(){}}const b=':root{--color-primary: #24ec71;--color-primary-contrast: #ffffff;--color-ink: #0f172a;--color-muted: #f1f5f9;--color-header: #f8fafc;--color-border: #e2e8f0;--color-border-strong: #cbd5f5;--color-nav-bg: #222222;--color-nav-text: #ffffff;--shadow-primary: 0 8px 18px rgba(31, 111, 235, .25);--focus-ring: #9ec5ff;--radius-pill: 999px;--radius-md: 12px;--color-page-bg: #ffffff;--color-page-text: #0f172a}body{background:var(--color-page-bg);color:var(--color-page-text);margin:0;font-family:Segoe UI,system-ui,-apple-system,sans-serif}:host([data-ui="button"]){display:inline-block}:host([data-ui="table"]){display:block}:host([data-ui="layout"]){display:block}:host([data-ui="sidebar"]){display:block}.btn{align-items:center;border:1px solid transparent;border-radius:var(--radius-pill);cursor:pointer;display:inline-flex;font-family:inherit;font-size:.95rem;font-weight:600;gap:.5rem;line-height:1;padding:.65rem 1.2rem;transition:transform .12s ease,box-shadow .12s ease,background-color .12s ease}.btn:focus-visible{outline:3px solid var(--focus-ring);outline-offset:2px}.btn:active:not(:disabled){transform:translateY(1px)}.btn:disabled{cursor:not-allowed;opacity:.6}.btn.primary{background:var(--color-primary);color:var(--color-primary-contrast);box-shadow:var(--shadow-primary)}.btn.secondary{background:var(--color-muted);color:var(--color-ink);border-color:var(--color-border-strong)}.btn.ghost{background:transparent;color:var(--color-primary);border-color:var(--color-border-strong)}.btn.has-icon{line-height:1.2}.btn .btn-icon{width:18px;height:18px;flex-shrink:0}.btn .btn-icon svg{width:100%;height:100%}.btn.icon-only{padding:.65rem;aspect-ratio:1}.btn.icon-only.sm{padding:.45rem}.btn.icon-only.lg{padding:.8rem}.btn.sm .btn-icon{width:14px;height:14px}.btn.lg .btn-icon{width:22px;height:22px}.btn.sm{font-size:.85rem;padding:.45rem .9rem;box-shadow:0 4px 12px #a7124426}.btn.md{font-size:.95rem;padding:.65rem 1.2rem}.btn.lg{font-size:1.05rem;padding:.8rem 1.5rem}.table-wrap{border:1px solid var(--color-border);border-radius:var(--radius-md);overflow:hidden}table{border-collapse:collapse;width:100%}thead{background:var(--color-header)}th,td{padding:.75rem 1rem;text-align:left;border-bottom:1px solid var(--color-border);font-size:.95rem;border-right:1px solid var(--color-border)}tr:last-child td{border-bottom:none}.align-left{text-align:left}.align-center{text-align:center}.align-right{text-align:right}.actions-cell{display:flex;gap:.5rem;justify-content:center}.action-btn{padding:.35rem .7rem;font-size:.8rem;border-radius:4px;cursor:pointer;border:1px solid var(--color-border-strong);background:var(--color-muted);color:var(--color-ink);transition:background-color .12s ease}.action-btn:hover{background:var(--color-border)}.action-btn.edit-btn{background:var(--color-primary);color:var(--color-primary-contrast);border-color:var(--color-primary)}.action-btn.edit-btn:hover{opacity:.85}.action-btn.delete-btn{background:#ef4444;color:#fff;border-color:#ef4444}.action-btn.delete-btn:hover{opacity:.85}.app-nav{padding:1rem;background:var(--color-nav-bg);color:var(--color-nav-text)}.app-link{color:var(--color-nav-text);margin-right:1rem;text-decoration:none}.signal-demo,.theme-toggle{margin-top:16px;display:flex;align-items:center;gap:12px}.data-table{margin-top:15px}.dashboard-layout{display:grid;grid-template-columns:220px minmax(0,1fr);gap:24px;padding:24px}.dashboard-sidebar{background:var(--color-muted);border:1px solid var(--color-border);border-radius:var(--radius-md);padding:18px}.sidebar-title{margin:0 0 12px;font-size:1rem}.sidebar-nav{display:flex;flex-direction:column;gap:10px}.sidebar-link{color:var(--color-ink);text-decoration:none;font-weight:600}.dashboard-main{display:flex;flex-direction:column;gap:12px}.dashboard-actions{display:flex;flex-wrap:wrap;gap:12px}@media (max-width: 900px){.dashboard-layout{grid-template-columns:1fr}}:host([data-ui="input"]){display:block}.input-wrapper{display:flex;flex-direction:column;gap:.35rem}.input-label{font-size:.9rem;font-weight:600;color:var(--color-ink)}.input-field{padding:.6rem .85rem;font-size:.95rem;font-family:inherit;border:1.5px solid var(--color-border);border-radius:6px;background:var(--color-page-bg);color:var(--color-page-text);transition:border-color .15s ease,box-shadow .15s ease;outline:none}.input-field::placeholder{color:#94a3b8}.input-field:focus{border-color:var(--color-primary);box-shadow:0 0 0 3px #24ec7126}.input-field:disabled{background:var(--color-muted);cursor:not-allowed;opacity:.7}.input-wrapper.invalid .input-field{border-color:#ef4444}.input-wrapper.invalid .input-field:focus{box-shadow:0 0 0 3px #ef444426}.input-error{font-size:.8rem;color:#ef4444;display:flex;align-items:center;gap:.25rem}.input-error.hidden{display:none}:host([data-ui="checkbox"]){display:inline-flex;align-items:center;cursor:pointer;-webkit-user-select:none;user-select:none}:host([data-ui="checkbox"][disabled]){cursor:not-allowed;opacity:.6}.checkbox-container{display:inline-flex;align-items:center;gap:.75rem}.checkbox-box{position:relative;display:inline-flex;align-items:center;justify-content:center;border:2px solid var(--color-border, #cbd5e1);border-radius:var(--radius-sm, 4px);background:#fff;transition:all .2s;flex-shrink:0;box-sizing:border-box}.checkbox-box.size-sm{min-width:16px;max-width:16px;min-height:16px;max-height:16px}.checkbox-box.size-md{min-width:18px;max-width:18px;min-height:18px;max-height:18px}.checkbox-box.size-lg{min-width:20px;max-width:20px;min-height:20px;max-height:20px}.checkbox-box:hover:not(.disabled){border-color:var(--color-primary, #24ec71)}.checkbox-box.checked,.checkbox-box.indeterminate{background:var(--color-primary, #24ec71);border-color:var(--color-primary, #24ec71)}.checkbox-box.disabled{background:var(--color-muted, #f1f5f9);cursor:not-allowed}.checkbox-icon{display:none;color:#fff;position:absolute}.checkbox-box.checked .checkbox-icon.check,.checkbox-box.indeterminate .checkbox-icon.minus{display:block}.checkbox-icon.check{width:12px;height:12px}.checkbox-icon.minus{width:10px;height:10px}.checkbox-label{font-size:.95rem;color:var(--color-ink, #0f172a);line-height:1.5}.checkbox-container.size-sm .checkbox-label{font-size:.875rem}.checkbox-container.size-lg .checkbox-label{font-size:1rem}input[type=checkbox]{position:absolute;opacity:0;pointer-events:none}.modal-backdrop{display:none;position:fixed;top:0;right:0;bottom:0;left:0;background:#00000080;-webkit-backdrop-filter:blur(4px);backdrop-filter:blur(4px);z-index:9999;animation:fadeIn .2s ease-out}.modal-backdrop.open{display:flex;align-items:center;justify-content:center;padding:1rem}.modal-content{background:var(--color-surface, white);border-radius:var(--radius-lg, 16px);box-shadow:0 20px 25px -5px #0000001a,0 10px 10px -5px #0000000a;max-height:90vh;display:flex;flex-direction:column;width:100%;animation:slideUp .2s ease-out}.modal-content.sm{max-width:400px}.modal-content.md{max-width:600px}.modal-content.lg{max-width:800px}.modal-content.xl{max-width:1200px}.modal-content.full{max-width:95vw}.modal-header{padding:1.5rem;border-bottom:1px solid var(--color-border, #e2e8f0);display:flex;align-items:center;justify-content:space-between}.modal-title{font-size:1.25rem;font-weight:600;color:var(--color-ink, #0f172a);margin:0}.modal-close{background:none;border:none;cursor:pointer;padding:.5rem;display:flex;align-items:center;justify-content:center;border-radius:var(--radius-md, 8px);color:var(--color-text-muted, #64748b);transition:all .2s}.modal-close:hover{background:var(--color-muted, #f1f5f9);color:var(--color-ink, #0f172a)}.modal-body{padding:1.5rem;overflow-y:auto;flex:1}.modal-footer{padding:1.5rem;border-top:1px solid var(--color-border, #e2e8f0);display:flex;gap:.75rem;justify-content:flex-end}@keyframes fadeIn{0%{opacity:0}to{opacity:1}}@keyframes slideUp{0%{opacity:0;transform:translateY(20px)}to{opacity:1;transform:translateY(0)}}:host([data-ui="select"]){display:block;width:90%}.select-container{position:relative;width:100%}.select-label{display:block;margin-bottom:.5rem;font-size:.875rem;font-weight:500;color:var(--color-ink, #0f172a)}.select-trigger{width:100%;padding:.625rem 1rem;background:#fff;border:1px solid var(--color-border, #e2e8f0);border-radius:var(--radius-md, 8px);display:flex;align-items:center;justify-content:space-between;cursor:pointer;transition:all .2s;font-size:.95rem;color:var(--color-ink, #0f172a)}.select-trigger:hover:not(:disabled){border-color:var(--color-primary, #24ec71)}.select-trigger:focus{outline:none;border-color:var(--color-primary, #24ec71);box-shadow:0 0 0 3px #24ec711a}.select-trigger:disabled{background:var(--color-muted, #f1f5f9);cursor:not-allowed;opacity:.6}.select-trigger.open{border-color:var(--color-primary, #24ec71)}.select-placeholder{color:var(--color-text-muted, #94a3b8);flex:1;text-align:left}.select-placeholder.has-selection{color:var(--color-ink, #0f172a)}.select-arrow{display:flex;transition:transform .2s;color:var(--color-text-muted, #64748b)}.select-arrow.open{transform:rotate(180deg)}.select-dropdown{position:absolute;top:calc(100% + .25rem);left:0;right:0;background:#fff;border:1px solid var(--color-border, #e2e8f0);border-radius:var(--radius-md, 8px);box-shadow:0 10px 15px -3px #0000001a,0 4px 6px -2px #0000000d;max-height:300px;overflow-y:auto;z-index:1000;display:none;animation:slideDown .15s ease-out}.select-dropdown.open{display:block}.select-search{width:100%;padding:.625rem 1rem;border:none;border-bottom:1px solid var(--color-border, #e2e8f0);font-size:.95rem;outline:none}.select-search:focus{background:var(--color-muted, #f1f5f9)}.select-option{padding:.625rem 1rem;cursor:pointer;transition:background .15s;color:var(--color-ink, #0f172a);font-size:.95rem}.select-option:hover:not(.disabled){background:var(--color-muted, #f1f5f9)}.select-option.selected{background:#24ec711a;color:var(--color-primary, #24ec71);font-weight:500}.select-option.disabled{opacity:.5;cursor:not-allowed}.select-empty{padding:1rem;text-align:center;color:var(--color-text-muted, #94a3b8);font-size:.875rem}@keyframes slideDown{0%{opacity:0;transform:translateY(-8px)}to{opacity:1;transform:translateY(0)}}:host([data-ui="pagination"]){display:block}.pagination-container{display:flex;align-items:center;justify-content:space-between;gap:1rem;flex-wrap:wrap}.pagination-info{font-size:.9rem;color:var(--color-ink);opacity:.7}.pagination{display:flex;align-items:center;gap:.25rem}.page-btn{min-width:2.5rem;height:2.5rem;padding:.5rem;border:1px solid var(--color-border);background:#fff;color:var(--color-ink);font-size:.9rem;font-weight:500;border-radius:6px;cursor:pointer;transition:all .2s ease;display:flex;align-items:center;justify-content:center}.page-btn:hover:not(:disabled):not(.active){background:var(--color-muted);border-color:var(--color-border-strong)}.page-btn:disabled{opacity:.4;cursor:not-allowed}.page-btn.active{background:var(--color-primary);color:var(--color-primary-contrast);border-color:var(--color-primary);font-weight:600}.page-btn.ellipsis{border:none;background:transparent;cursor:default;pointer-events:none}.nav-btn{padding:.5rem .75rem}.nav-btn svg{width:16px;height:16px}:host([data-ui="date-picker"]){display:inline-block;width:100%;max-width:300px}.date-picker-container{position:relative;display:flex;flex-direction:column;gap:.5rem}.date-input-wrapper{position:relative;display:flex;align-items:center;border:1px solid var(--color-border);border-radius:var(--radius-md);background:#fff;transition:all .2s ease}.date-input-wrapper:hover:not(.disabled){border-color:var(--color-border-strong)}.date-input-wrapper:focus-within{border-color:var(--color-primary);box-shadow:0 0 0 3px #24ec711a;outline:none}.date-input-wrapper.disabled{background:var(--color-muted);cursor:not-allowed;opacity:.6}.formatted-input{flex:1;border:none;padding:.75rem 1rem;font-size:.95rem;font-family:inherit;background:transparent;color:var(--color-ink);outline:none}.formatted-input:disabled{cursor:not-allowed;color:var(--color-ink);opacity:.7}.formatted-input::placeholder{color:#94a3b8;opacity:.7}.formatted-input.invalid{color:#dc2626}.hidden-date-input{position:absolute;opacity:0;pointer-events:none;width:0;height:0}.calendar-btn{padding:.5rem;margin-right:.5rem;border:none;background:transparent;cursor:pointer;display:flex;align-items:center;justify-content:center;color:var(--color-ink);opacity:.6;transition:all .2s ease;border-radius:6px}.calendar-btn:hover:not(:disabled){background:var(--color-muted);opacity:1}.calendar-btn:disabled{cursor:not-allowed;opacity:.3}.calendar-icon{width:20px;height:20px}.format-label{font-size:.75rem;color:var(--color-ink);opacity:.6;padding:0 .25rem;font-weight:500}';class y extends p{connectedCallback(){this.setAttribute("data-ui","sidebar"),super.connectedCallback()}render(){this.shadowRoot.innerHTML=`
2
+ <style>${b}</style>
3
+ <aside class="dashboard-sidebar">
4
+ <h2 class="sidebar-title">Workspace</h2>
5
+ <nav class="sidebar-nav">
6
+ <a class="sidebar-link" href="/" data-link>Button Demo</a>
7
+ <a class="sidebar-link" href="/input-demo" data-link>Input Demo</a>
8
+ <a class="sidebar-link" href="/date-picker" data-link>Date Picker Demo</a>
9
+ <a class="sidebar-link" href="/table-demo" data-link>Table Demo</a>
10
+ <a class="sidebar-link" href="/modal" data-link>Modal Demo</a>
11
+ <a class="sidebar-link" href="/select" data-link>Select Demo</a>
12
+ <a class="sidebar-link" href="/checkbox" data-link>Checkbox Demo</a>
13
+ </nav>
14
+ </aside>
15
+ `}}customElements.define("app-sidebar",y);class k extends p{connectedCallback(){this.setAttribute("data-ui","button"),super.connectedCallback()}static get observedAttributes(){return["variant","size","disabled","type","icon","icon-position"]}attributeChangedCallback(){this.render()}getVariant(){const e=this.getAttribute("variant");return e==="secondary"||e==="ghost"?e:"primary"}getSize(){const e=this.getAttribute("size");return e==="sm"||e==="lg"?e:"md"}getType(){return this.getAttribute("type")??"button"}getIcon(){var a;const e=this.getAttribute("icon");if(!e)return null;const o=e.trim();return{html:`<span class="btn-icon">${((a=x.icons[o])==null?void 0:a.toSvg())||""}</span>`,name:o}}getIconPosition(){return this.getAttribute("icon-position")==="right"?"right":"left"}render(){const e=this.getVariant(),o=this.getSize(),t=this.hasAttribute("disabled"),a=this.getType(),s=this.getIcon(),u=this.getIconPosition(),n=s!==null,d=s?s.html:"",i=this.innerHTML.trim(),h=n&&!i;let l;n&&i?l=u==="left"?`${d}<span>${i}</span>`:`<span>${i}</span>${d}`:n?l=d:l=i,this.shadowRoot.innerHTML=`
16
+ <style>${b}</style>
17
+ <button
18
+ part="button"
19
+ class="btn ${e} ${o}${n?" has-icon":""}${h?" icon-only":""}"
20
+ type="${a}"
21
+ ${t?"disabled":""}
22
+ >
23
+ ${l}
24
+ </button>
25
+ `}}customElements.define("ui-button",k);class w extends p{connectedCallback(){this.setAttribute("data-ui","layout"),super.connectedCallback()}render(){this.shadowRoot.innerHTML=`
26
+ <style>${b}</style>
27
+ <nav class="app-nav">
28
+ Dashboard
29
+ <ui-button id="theme-toggle" variant="ghost" size="sm">Toggle Theme</ui-button>
30
+ </nav>
31
+ <div class="dashboard-layout">
32
+ <app-sidebar></app-sidebar>
33
+ <main class="dashboard-main">
34
+ <slot></slot>
35
+ </main>
36
+ </div>
37
+ `;const e=this.shadowRoot.querySelector("#theme-toggle");e&&e.addEventListener("click",()=>{const o=m.getState().theme==="shadcn"?"light":"shadcn";m.setState({theme:o}),this.render()})}}customElements.define("app-layout",w);export{p as B,b as s};
@@ -0,0 +1,157 @@
1
+ var E=Object.defineProperty;var C=(n,t,e)=>t in n?E(n,t,{enumerable:!0,configurable:!0,writable:!0,value:e}):n[t]=e;var v=(n,t,e)=>C(n,typeof t!="symbol"?t+"":t,e);import{B as y,s as w}from"./app-layout-D81L3er1.js";import"./index-DJpTIOwN.js";import"./vendor-BvJLUv9i.js";const z=`
2
+ <div class="demo-container">
3
+ <h1>Checkbox Component Demo</h1>
4
+ <p>Flexible checkbox with sizes, states, and indeterminate support.</p>
5
+
6
+ <div class="demo-section">
7
+ <h2>Basic Checkboxes</h2>
8
+ <div class="checkbox-group">
9
+ <ui-checkbox id="basic1" label="Accept terms and conditions"></ui-checkbox>
10
+ <ui-checkbox id="basic2" label="Subscribe to newsletter" checked></ui-checkbox>
11
+ <ui-checkbox id="basic3" label="Disabled checkbox" disabled></ui-checkbox>
12
+ <ui-checkbox id="basic4" label="Disabled & checked" disabled checked></ui-checkbox>
13
+ </div>
14
+ </div>
15
+
16
+ <div class="demo-section">
17
+ <h2>Checkbox Sizes</h2>
18
+ <div class="checkbox-group">
19
+ <ui-checkbox id="size1" label="Small checkbox" size="sm"></ui-checkbox>
20
+ <ui-checkbox id="size2" label="Medium checkbox (default)" size="md"></ui-checkbox>
21
+ <ui-checkbox id="size3" label="Large checkbox" size="lg"></ui-checkbox>
22
+ </div>
23
+ </div>
24
+
25
+ <div class="demo-section">
26
+ <h2>Indeterminate State</h2>
27
+ <p style="color: var(--color-text-muted); font-size: 0.875rem; margin-bottom: 1rem;">
28
+ Useful for "select all" scenarios where some items are selected.
29
+ </p>
30
+ <div style="background: white; padding: 1.5rem; border-radius: var(--radius-lg); border: 1px solid var(--color-border);">
31
+ <ui-checkbox id="selectAll" label="Select All" size="md"></ui-checkbox>
32
+ <div style="margin-left: 2rem; margin-top: 1rem;" class="checkbox-group">
33
+ <ui-checkbox class="item-checkbox" label="Item 1" size="sm"></ui-checkbox>
34
+ <ui-checkbox class="item-checkbox" label="Item 2" size="sm"></ui-checkbox>
35
+ <ui-checkbox class="item-checkbox" label="Item 3" size="sm"></ui-checkbox>
36
+ <ui-checkbox class="item-checkbox" label="Item 4" size="sm"></ui-checkbox>
37
+ </div>
38
+ </div>
39
+ </div>
40
+
41
+ <div class="demo-section">
42
+ <h2>Checkbox Group (Form)</h2>
43
+ <form id="preferencesForm" style="max-width: 600px;">
44
+ <fieldset style="border: 1px solid var(--color-border); border-radius: var(--radius-lg); padding: 1.5rem;">
45
+ <legend style="font-weight: 600; padding: 0 0.5rem;">Notification Preferences</legend>
46
+ <div class="checkbox-group">
47
+ <ui-checkbox id="emailNotif" label="Email notifications" checked></ui-checkbox>
48
+ <ui-checkbox id="smsNotif" label="SMS notifications"></ui-checkbox>
49
+ <ui-checkbox id="pushNotif" label="Push notifications" checked></ui-checkbox>
50
+ <ui-checkbox id="weeklyDigest" label="Weekly digest"></ui-checkbox>
51
+ </div>
52
+ </fieldset>
53
+
54
+ <div style="margin-top: 1.5rem; display: flex; gap: 1rem;">
55
+ <ui-button type="submit" variant="primary" icon="save">Save Preferences</ui-button>
56
+ <ui-button type="button" id="resetPreferences" variant="ghost">Reset</ui-button>
57
+ </div>
58
+ </form>
59
+ <div id="formResult" class="result-display" style="display: none; margin-top: 1rem;">
60
+ <strong>Saved Preferences:</strong><br>
61
+ <span id="formValue"></span>
62
+ </div>
63
+ </div>
64
+
65
+ <div class="demo-section">
66
+ <h2>Event Handling</h2>
67
+ <div style="background: white; padding: 1.5rem; border-radius: var(--radius-lg); border: 1px solid var(--color-border);">
68
+ <ui-checkbox id="eventCheckbox" label="Click me to trigger event"></ui-checkbox>
69
+ </div>
70
+ <div id="eventResult" class="result-display" style="display: none; margin-top: 1rem;">
71
+ <strong>Event Log:</strong><br>
72
+ <div id="eventLog" style="font-family: monospace; font-size: 0.875rem; margin-top: 0.5rem;"></div>
73
+ </div>
74
+ </div>
75
+ </div>
76
+ `,R=`
77
+ .demo-container {
78
+ padding: 2rem;
79
+ max-width: 1200px;
80
+ margin: 0 auto;
81
+ }
82
+
83
+ .demo-container h1 {
84
+ font-size: 2rem;
85
+ margin-bottom: 0.5rem;
86
+ color: var(--color-ink);
87
+ }
88
+
89
+ .demo-container > p {
90
+ color: var(--color-text-muted);
91
+ margin-bottom: 2rem;
92
+ }
93
+
94
+ .demo-section {
95
+ margin-bottom: 3rem;
96
+ padding-bottom: 2rem;
97
+ border-bottom: 1px solid var(--color-border);
98
+ }
99
+
100
+ .demo-section:last-child {
101
+ border-bottom: none;
102
+ }
103
+
104
+ .demo-section h2 {
105
+ font-size: 1.5rem;
106
+ margin-bottom: 1rem;
107
+ color: var(--color-ink);
108
+ }
109
+
110
+ .checkbox-group {
111
+ display: flex;
112
+ flex-direction: column;
113
+ gap: 1rem;
114
+ }
115
+
116
+ .result-display {
117
+ padding: 1rem;
118
+ background: var(--color-muted);
119
+ border-radius: var(--radius-md);
120
+ border-left: 4px solid var(--color-primary);
121
+ }
122
+
123
+ fieldset {
124
+ margin: 0;
125
+ }
126
+
127
+ legend {
128
+ color: var(--color-ink);
129
+ }
130
+ `;class I extends y{constructor(){super(...arguments);v(this,"checked",this.useSignal(!1));v(this,"indeterminate",this.useSignal(!1))}connectedCallback(){this.setAttribute("data-ui","checkbox"),super.connectedCallback()}static get observedAttributes(){return["checked","disabled","indeterminate"]}attributeChangedCallback(e,r,i){e==="checked"&&r!==i&&this.checked.set(i!==null),e==="indeterminate"&&r!==i&&this.indeterminate.set(i!==null),this.render()}handleChange(){if(this.hasAttribute("disabled"))return;this.indeterminate.get()&&(this.indeterminate.set(!1),this.removeAttribute("indeterminate"));const e=!this.checked.get();this.checked.set(e),e?this.setAttribute("checked",""):this.removeAttribute("checked"),this.dispatchEvent(new CustomEvent("checkbox-change",{bubbles:!0,composed:!0,detail:{checked:e}}))}setChecked(e){this.checked.set(e),e?this.setAttribute("checked",""):this.removeAttribute("checked"),this.indeterminate.set(!1),this.removeAttribute("indeterminate")}setIndeterminate(e){this.indeterminate.set(e),e?this.setAttribute("indeterminate",""):this.removeAttribute("indeterminate")}render(){const e=this.checked.get(),r=this.indeterminate.get(),i=this.hasAttribute("disabled"),a=this.getAttribute("label")||"",m=this.getAttribute("size")||"md",l={sm:"size-sm",md:"size-md",lg:"size-lg"};this.shadowRoot.innerHTML=`
131
+ <style>${w}</style>
132
+
133
+ <label class="checkbox-container ${l[m]}">
134
+ <input
135
+ type="checkbox"
136
+ ${e?"checked":""}
137
+ ${i?"disabled":""}
138
+ >
139
+ <div class="checkbox-box ${l[m]} ${e?"checked":""} ${r?"indeterminate":""} ${i?"disabled":""}" part="checkbox">
140
+ <svg class="checkbox-icon check" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="3">
141
+ <polyline points="20 6 9 17 4 12"></polyline>
142
+ </svg>
143
+ <svg class="checkbox-icon minus" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="3">
144
+ <line x1="5" y1="12" x2="19" y2="12"></line>
145
+ </svg>
146
+ </div>
147
+ ${a?`<span class="checkbox-label">${a}</span>`:"<slot></slot>"}
148
+ </label>
149
+ `;const o=this.shadowRoot.querySelector(".checkbox-container");o==null||o.addEventListener("click",d=>{d.preventDefault(),this.handleChange()})}}customElements.define("ui-checkbox",I);class S extends y{async connectedCallback(){super.connectedCallback(),await Promise.all([customElements.whenDefined("ui-checkbox"),customElements.whenDefined("ui-button")]),await new Promise(t=>setTimeout(t,10)),this.setupEventListeners()}setupEventListeners(){const t=this.shadowRoot.getElementById("selectAll"),e=this.shadowRoot.querySelectorAll(".item-checkbox"),r=()=>{const s=Array.from(e).filter(c=>c.hasAttribute("checked")).length;s===0?t==null||t.setChecked(!1):s===e.length?t==null||t.setChecked(!0):t==null||t.setIndeterminate(!0)};t==null||t.addEventListener("checkbox-change",s=>{const c=s.detail.checked;e.forEach(g=>{g.setChecked(c)})}),e.forEach(s=>{s.addEventListener("checkbox-change",r)}),r();const i=this.shadowRoot.getElementById("preferencesForm"),a=this.shadowRoot.getElementById("formResult"),m=this.shadowRoot.getElementById("formValue"),l=this.shadowRoot.getElementById("resetPreferences"),o=this.shadowRoot.getElementById("emailNotif"),d=this.shadowRoot.getElementById("smsNotif"),h=this.shadowRoot.getElementById("pushNotif"),b=this.shadowRoot.getElementById("weeklyDigest");i==null||i.addEventListener("submit",s=>{s.preventDefault();const c={email:(o==null?void 0:o.hasAttribute("checked"))||!1,sms:(d==null?void 0:d.hasAttribute("checked"))||!1,push:(h==null?void 0:h.hasAttribute("checked"))||!1,weekly:(b==null?void 0:b.hasAttribute("checked"))||!1};a&&m&&(a.style.display="block",m.innerHTML=`
150
+ Email: <strong>${c.email?"✓ Enabled":"✗ Disabled"}</strong><br>
151
+ SMS: <strong>${c.sms?"✓ Enabled":"✗ Disabled"}</strong><br>
152
+ Push: <strong>${c.push?"✓ Enabled":"✗ Disabled"}</strong><br>
153
+ Weekly Digest: <strong>${c.weekly?"✓ Enabled":"✗ Disabled"}</strong>
154
+ `)}),l==null||l.addEventListener("click",()=>{o==null||o.setChecked(!0),d==null||d.setChecked(!1),h==null||h.setChecked(!0),b==null||b.setChecked(!1),a&&(a.style.display="none")});const k=this.shadowRoot.getElementById("eventCheckbox"),p=this.shadowRoot.getElementById("eventResult"),u=this.shadowRoot.getElementById("eventLog");let f=0;k==null||k.addEventListener("checkbox-change",s=>{f++;const c=new Date().toLocaleTimeString(),g=s.detail.checked?"checked":"unchecked";if(p&&u){p.style.display="block";const x=document.createElement("div");for(x.style.color=s.detail.checked?"var(--color-primary)":"var(--color-text-muted)",x.textContent=`[${c}] Event #${f}: ${g}`,u.prepend(x);u.children.length>5;)u.removeChild(u.lastChild)}})}render(){this.shadowRoot.innerHTML=`
155
+ <style>${R}</style>
156
+ ${z}
157
+ `}}customElements.define("checkbox-demo-page",S);
@@ -1,4 +1,4 @@
1
- var m=Object.defineProperty;var b=(e,t,n)=>t in e?m(e,t,{enumerable:!0,configurable:!0,writable:!0,value:n}):e[t]=n;var u=(e,t,n)=>b(e,typeof t!="symbol"?t+"":t,n);import{B as v,s as g}from"./app-layout-BWpUyzvG.js";import"./table-CB6WCNz5.js";import{s as i}from"./index-BZ8Wp8z7.js";import"./vendor-BvJLUv9i.js";const y=`<h1>Button</h1>
1
+ var m=Object.defineProperty;var b=(e,t,n)=>t in e?m(e,t,{enumerable:!0,configurable:!0,writable:!0,value:n}):e[t]=n;var u=(e,t,n)=>b(e,typeof t!="symbol"?t+"":t,n);import{B as v,s as g}from"./app-layout-D81L3er1.js";import"./table-BoHSrBty.js";import{s as i}from"./index-DJpTIOwN.js";import"./vendor-BvJLUv9i.js";const y=`<h1>Button</h1>
2
2
  <p>Your enterprise-ready Web Components SPA is running 🚀</p>
3
3
  <div class="dashboard-actions">
4
4
  <ui-button variant="primary" size="md">Get Started</ui-button>