@teamprodevs/appsmith-custom-table 1.1.4 → 1.1.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
@@ -3,33 +3,56 @@
3
3
  [![npm version](https://img.shields.io/npm/v/%40teamprodevs/appsmith-custom-table.svg)](https://www.npmjs.com/package/@teamprodevs/appsmith-custom-table)
4
4
  [![License](https://img.shields.io/badge/license-MIT-blue.svg)](#license)
5
5
  [![Storybook](https://img.shields.io/badge/storybook-live-ff4785.svg)](https://custom-appsmith-table.netlify.app/)
6
+ [![TypeScript](https://img.shields.io/badge/TypeScript-5.x-blue.svg)](https://www.typescriptlang.org/)
6
7
 
7
- A highly configurable table system built for Appsmith custom widgets. It marries React 18, TanStack Table v8, and TailwindCSS to deliver both server-side infinite lists and lightweight client-side tables with the same API surface.
8
+ A highly configurable table component built for Appsmith custom widgets. It combines React 18, TanStack Table v8, and TailwindCSS to deliver a powerful client-side table that integrates seamlessly with Appsmith's data sources including PostgreSQL, MongoDB, Elasticsearch, and REST APIs.
9
+
10
+ > ⚠️ **Maintenance Notice**: This project was developed as a job task and is **not actively maintained**. If you need additional features or bug fixes, please [fork this repository](https://github.com/smarts-uz/appsmith-custom-table/fork) and maintain your own version.
11
+
12
+ ## 🔗 Quick Links
13
+
14
+ | Resource | Link |
15
+ |----------|------|
16
+ | 📚 **Storybook Demo** | [custom-appsmith-table.netlify.app](https://custom-appsmith-table.netlify.app/?path=/story/appsmith-table--translated-table) |
17
+ | 📦 **NPM Package** | [npmjs.com/package/@teamprodevs/appsmith-custom-table](https://www.npmjs.com/package/@teamprodevs/appsmith-custom-table) |
18
+ | 🎯 **Appsmith Example** | [Live Appsmith Demo](https://custom-table.appsmith.com/app/appsmith-custom-table/basic-example-695f8fe01bbc1832a1e36e11?environment=production) |
19
+ | 💻 **GitHub Repository** | [github.com/smarts-uz/appsmith-custom-table](https://github.com/smarts-uz/appsmith-custom-table) |
8
20
 
9
21
  ## Features
10
22
 
11
23
  - Full Appsmith custom component support (bundled + CDN).
12
- - Dual rendering modes: SSR infinite loading and client-side in-memory tables.
13
- - Typed configuration powered by Zod schemas for columns, fetchers, and models.
24
+ - Client-side pagination with infinite scroll support.
25
+ - Tight integration with Appsmith's data models (PostgreSQL, MongoDB, Elasticsearch, REST APIs).
26
+ - Typed configuration powered by Zod schemas for validation.
14
27
  - Rich styling hooks with Tailwind-first tokenization.
15
28
  - Action hooks, event callbacks, and controlled `updateModel` APIs.
16
- - Designed for pgrest/dbtorest pagination models.
29
+ - Conditional row styling based on cell values.
30
+ - Multi-language support (i18n) for column headers and action labels.
31
+ - Built-in formatters for phone, date, datetime, and currency.
32
+ - Compatible with pgrest/dbtorest pagination patterns.
17
33
 
18
34
  ## Table of Contents
19
35
 
20
- 1. [Demo](#demo)
36
+ 1. [Quick Links](#-quick-links)
21
37
  2. [Installation](#installation)
22
38
  3. [CDN Usage](#cdn-usage)
23
39
  4. [Quick Start](#quick-start)
24
40
  5. [Usage](#usage)
25
- 6. [Configuration Schemas](#configuration-schemas)
26
- 7. [Customization](#customization)
27
- 8. [SSR Table Capabilities](#ssr-table-capabilities)
28
- 9. [Client-Side Table Highlights](#client-side-table-highlights)
29
- 10. [Development](#development)
30
- 11. [Contributing](#contributing)
31
- 12. [License](#license)
32
- 13. [Acknowledgements](#acknowledgements)
41
+ 6. [API Reference](#api-reference)
42
+ - [TableModel Props](#tablemodel-props)
43
+ - [Column Schema](#column-schema)
44
+ - [Column Types](#column-types)
45
+ 7. [Row Actions](#row-actions)
46
+ 8. [Conditional Styling](#conditional-styling)
47
+ 9. [Translations (i18n)](#translations-i18n)
48
+ 10. [Customization](#customization)
49
+ - [Styles](#styles)
50
+ - [CSS Variables](#css-variables)
51
+ 11. [Events](#events)
52
+ 12. [Development](#development)
53
+ 13. [Contributing](#contributing)
54
+ 14. [License](#license)
55
+ 15. [Acknowledgements](#acknowledgements)
33
56
 
34
57
  ## Demo
35
58
 
@@ -54,16 +77,18 @@ Ideal for Appsmith widgets where bundling is not available.
54
77
 
55
78
  ## Quick Start
56
79
 
57
- 1. Define a schema describing each columns type, filtering, and sorting behavior.
58
- 2. Render the `AppsmithTable` with either `data` (client) or `tableModel` (SSR).
59
- 3. Optionally pass custom styles, actions, events, and an `updateModel` handler for controlled flows.
80
+ 1. Define a schema describing each column's type and display options.
81
+ 2. Pass your Appsmith query data to the `ClientTable` component.
82
+ 3. Wire up `triggerEvent` and `updateModel` callbacks to Appsmith's APIs.
83
+ 4. Optionally add custom styles, actions, and conditional formatting.
60
84
 
61
85
  ## Usage
62
86
 
63
87
  ### Client-side Table
64
88
 
65
89
  ```tsx
66
- import { AppsmithTable } from "@teamprodevs/appsmith-custom-table";
90
+ import { ClientTable } from "@teamprodevs/appsmith-custom-table";
91
+ import "@teamprodevs/appsmith-custom-table/dist/styles.css";
67
92
 
68
93
  const data = [
69
94
  { id: 1, name: "Alice", age: 25 },
@@ -71,83 +96,468 @@ const data = [
71
96
  ];
72
97
 
73
98
  const schema = {
74
- id: { type: "text", filter: true, sort: true },
75
- name: { type: "text", filter: true, sort: true },
76
- age: { type: "number", filter: true, sort: true },
99
+ id: { type: "text", title: { en: "ID", uz: "ID" } },
100
+ name: { type: "text", title: { en: "Name", uz: "Ism" } },
101
+ age: { type: "text", title: { en: "Age", uz: "Yosh" } },
77
102
  };
78
103
 
79
- const ClientTable = () => <AppsmithTable schema={schema} data={data} />;
104
+ const MyTable = () => (
105
+ <ClientTable
106
+ tableData={data}
107
+ schema={schema}
108
+ locale="en"
109
+ triggerEvent={(event, payload) => console.log(event, payload)}
110
+ updateModel={(model) => console.log(model)}
111
+ onModelChange={(model) => console.log(model)}
112
+ />
113
+ );
80
114
  ```
81
115
 
82
- ### SSR Infinite Table
116
+ ### Infinite Scroll with Appsmith
117
+
118
+ The table triggers `onLoadMore` events for pagination. Wire this to your Appsmith query:
83
119
 
84
120
  ```tsx
85
- import { AppsmithTable } from "@teamprodevs/appsmith-custom-table";
121
+ import { ClientTable } from "@teamprodevs/appsmith-custom-table";
86
122
 
123
+ // In your Appsmith custom widget
87
124
  const tableModel = {
88
- fetcher: {
89
- url: "https://api.example.com/users",
90
- method: "GET",
91
- perPage: 20,
92
- paginationKeys: { offset: "offset", limit: "limit" },
93
- },
125
+ tableData: appsmith.model.queryData, // Data from your Appsmith query
94
126
  schema,
95
- updateModel: (state) => console.log("table state", state),
127
+ locale: "en",
128
+ limit: 20,
129
+ max_count: appsmith.model.totalCount, // Total rows from your API
130
+ triggerEvent: (event, payload) => appsmith.triggerEvent(event, payload),
131
+ updateModel: (model) => appsmith.updateModel(model),
132
+ onModelChange: (model) => console.log("table state", model),
133
+ };
134
+
135
+ const UsersTable = () => <ClientTable {...tableModel} />;
136
+ ```
137
+
138
+ ## API Reference
139
+
140
+ ### TableModel Props
141
+
142
+ The `ClientTable` component accepts the following props (all validated via Zod schemas):
143
+
144
+ | Prop | Type | Required | Default | Description |
145
+ |------|------|----------|---------|-------------|
146
+ | `tableData` | `any[]` | Yes | `[]` | Array of row data objects |
147
+ | `schema` | `Schema` | Yes | - | Column definitions (see [Column Schema](#column-schema)) |
148
+ | `locale` | `string` | Yes | - | Active language code for translations (e.g., `"en"`, `"uz"`, `"ru"`) |
149
+ | `triggerEvent` | `TriggerEvent` | Yes | - | Callback to trigger Appsmith events |
150
+ | `updateModel` | `UpdateModel` | Yes | - | Callback to update Appsmith model state |
151
+ | `onModelChange` | `OnModelChange` | Yes | - | Callback fired when table model changes |
152
+ | `limit` | `number` | No | `20` | Number of rows per page |
153
+ | `max_count` | `number` | No | `20` | Maximum total rows (for pagination) |
154
+ | `indexColumn` | `IndexColumn` | No | - | Configuration for row index column |
155
+ | `actionColumn` | `ActionColumn` | No | - | Configuration for action buttons column |
156
+ | `conditionalRowStyles` | `ConditionalRowStyle[]` | No | - | Rules for conditional row styling |
157
+ | `styles` | `AppsmithTableStyles` | No | - | Custom styling configuration |
158
+ | `rowSelectionAction` | `string` | No | - | Event name triggered on row selection |
159
+
160
+ ### Column Schema
161
+
162
+ Each column in the `schema` object is defined with these options:
163
+
164
+ ```typescript
165
+ const schema = {
166
+ column_key: {
167
+ type: "text", // Column type (see Column Types)
168
+ size: "md", // Width: "xs" | "sm" | "md" | "lg"
169
+ title: { // Localized column headers
170
+ en: "English Title",
171
+ uz: "O'zbek Sarlavha",
172
+ ru: "Русский заголовок"
173
+ },
174
+ className: "custom-class" // Custom CSS classes
175
+ }
176
+ };
177
+ ```
178
+
179
+ | Option | Type | Required | Default | Description |
180
+ |--------|------|----------|---------|-------------|
181
+ | `type` | `ColumnType` | No | `"text"` | Data type for formatting |
182
+ | `size` | `"xs" \| "sm" \| "md" \| "lg"` | No | `"md"` | Column width preset |
183
+ | `title` | `Record<string, string>` | No | - | Localized headers by language code |
184
+ | `className` | `string` | No | - | Custom CSS classes for column |
185
+
186
+ ### Column Types
187
+
188
+ The table supports 6 column types with automatic formatting:
189
+
190
+ | Type | Description | Example Output |
191
+ |------|-------------|----------------|
192
+ | `text` | Plain text display (default) | `"John Doe"` |
193
+ | `url` | Clickable link (special format) | `<a href="...">Display Text</a>` |
194
+ | `phone` | Phone number formatting | `99 123 45 67` |
195
+ | `date` | Date formatting | `15-03-2024` |
196
+ | `datetime` | Date and time formatting | `15-03-2024 14:30` |
197
+ | `currency` | Currency with thousand separators | `1 234 567` |
198
+
199
+ #### URL Column Format
200
+
201
+ For URL columns, use the special format `"Display Text|||https://url.com"`:
202
+
203
+ ```typescript
204
+ const data = [
205
+ {
206
+ link: "Visit Site|||https://example.com",
207
+ // Renders as clickable "Visit Site" link
208
+ }
209
+ ];
210
+
211
+ const schema = {
212
+ link: { type: "url", title: { en: "Link" } }
96
213
  };
214
+ ```
215
+
216
+ When clicked, triggers `onRedirect` event with the URL.
217
+
218
+ ## Row Actions
219
+
220
+ Add interactive action buttons to each row using the `actionColumn` configuration:
221
+
222
+ ```typescript
223
+ import { ClientTable } from "@teamprodevs/appsmith-custom-table";
97
224
 
98
- const UsersTable = () => <AppsmithTable tableModel={tableModel} />;
225
+ const tableModel = {
226
+ tableData: data,
227
+ schema: schema,
228
+ locale: "en",
229
+ actionColumn: {
230
+ enable: true,
231
+ pin: "right", // "left" | "right"
232
+ type: "outline", // Button variant
233
+ icon: "MoreVertical", // Lucide icon for dropdown trigger
234
+ actions: [
235
+ {
236
+ title: { en: "View", uz: "Ko'rish", ru: "Просмотр" },
237
+ onClick: "onView", // Event name to trigger
238
+ icon: "Eye", // Lucide icon name
239
+ className: "text-blue-600"
240
+ },
241
+ {
242
+ title: { en: "Edit", uz: "Tahrirlash", ru: "Редактировать" },
243
+ onClick: "onEdit",
244
+ icon: "Pencil"
245
+ },
246
+ {
247
+ title: { en: "Delete", uz: "O'chirish", ru: "Удалить" },
248
+ onClick: "onDelete",
249
+ icon: "Trash2",
250
+ className: "text-red-600"
251
+ }
252
+ ]
253
+ },
254
+ triggerEvent: (event, payload) => {
255
+ // payload contains { row: <row data> }
256
+ console.log(event, payload);
257
+ },
258
+ // ... other props
259
+ };
99
260
  ```
100
261
 
101
- ## Configuration Schemas
262
+ ### Action Column Options
263
+
264
+ | Option | Type | Required | Default | Description |
265
+ |--------|------|----------|---------|-------------|
266
+ | `enable` | `boolean` | Yes | - | Enable/disable action column |
267
+ | `actions` | `RowAction[]` | Yes | - | Array of action definitions |
268
+ | `pin` | `"left" \| "right"` | No | `"right"` | Pin column position |
269
+ | `type` | `string` | No | `"default"` | Button variant |
270
+ | `icon` | `LucideIconName` | No | - | Icon for dropdown trigger |
271
+
272
+ ### Button Variants
102
273
 
103
- Every table is fully typed using Zod schemas. Key primitives include:
274
+ Available button variants: `"default"`, `"destructive"`, `"outline"`, `"secondary"`, `"ghost"`, `"link"`
104
275
 
105
- - **`ColumnItemSchema`**: Describes column type (`text`, `number`, etc.), sorting, filtering, sizing, visibility, and formatting.
106
- - **`FetcherSchema`**: Encapsulates REST config—method, headers, query/body params, pagination keys, debounce, and optimistic flags.
107
- - **`TableModelSchema`**: The orchestration layer combining schema, fetcher, selection settings, actions, row styles, and callbacks.
276
+ ### Supported Icons
108
277
 
109
- These schemas keep your tables consistent, validated, and shareable across projects.
278
+ All [Lucide React](https://lucide.dev/icons/) icons are supported. Use the icon name as a string (e.g., `"Eye"`, `"Pencil"`, `"Trash2"`, `"Activity"`, `"AlarmClockPlus"`).
279
+
280
+ ## Conditional Styling
281
+
282
+ Apply dynamic styles to rows based on cell values using `conditionalRowStyles`:
283
+
284
+ ```typescript
285
+ const tableModel = {
286
+ // ... other props
287
+ conditionalRowStyles: [
288
+ // Highlight rows where used_days >= 150
289
+ {
290
+ column: "used_days",
291
+ operator: ">=",
292
+ value: 150,
293
+ className: "bg-yellow-200"
294
+ },
295
+ // Red background for used_days >= 300
296
+ {
297
+ column: "used_days",
298
+ operator: ">=",
299
+ value: 300,
300
+ className: "bg-red-400"
301
+ },
302
+ // Compare two columns: highlight when payment < debt
303
+ {
304
+ column: "total_payment",
305
+ operator: "<",
306
+ value: { columnRef: "debt_amount" },
307
+ className: "text-red-800 font-bold"
308
+ },
309
+ // Green when payment >= debt
310
+ {
311
+ column: "total_payment",
312
+ operator: ">=",
313
+ value: { columnRef: "debt_amount" },
314
+ className: "text-green-800 font-bold"
315
+ }
316
+ ]
317
+ };
318
+ ```
319
+
320
+ ### Conditional Style Options
321
+
322
+ | Option | Type | Required | Description |
323
+ |--------|------|----------|-------------|
324
+ | `column` | `string` | Yes | Column key to evaluate |
325
+ | `operator` | `RowStyleOperator` | Yes | Comparison operator |
326
+ | `value` | `string \| number \| boolean \| { columnRef: string }` | Yes | Value to compare against (or another column) |
327
+ | `className` | `string` | Yes | Tailwind/CSS classes to apply |
328
+
329
+ ### Supported Operators
330
+
331
+ | Operator | Description |
332
+ |----------|-------------|
333
+ | `>` | Greater than |
334
+ | `<` | Less than |
335
+ | `>=` | Greater than or equal |
336
+ | `<=` | Less than or equal |
337
+ | `===` | Strict equality |
338
+ | `==` | Loose equality |
339
+ | `!==` | Strict inequality |
340
+ | `!=` | Loose inequality |
341
+ | `contains` | String contains |
342
+ | `startsWith` | String starts with |
343
+ | `endsWith` | String ends with |
344
+ | `isEmpty` | Value is empty |
345
+ | `isNotEmpty` | Value is not empty |
346
+
347
+ ### Column-to-Column Comparison
348
+
349
+ Use `{ columnRef: "column_name" }` to compare against another column's value:
350
+
351
+ ```typescript
352
+ {
353
+ column: "actual_amount",
354
+ operator: "<",
355
+ value: { columnRef: "expected_amount" },
356
+ className: "text-red-600"
357
+ }
358
+ ```
359
+
360
+ ## Translations (i18n)
361
+
362
+ The table supports multi-language column headers and action labels:
363
+
364
+ ### Column Header Translations
365
+
366
+ ```typescript
367
+ const schema = {
368
+ customer_name: {
369
+ title: {
370
+ en: "Customer Name",
371
+ uz: "Mijoz Ismi",
372
+ ru: "Имя клиента"
373
+ },
374
+ type: "text"
375
+ },
376
+ phone: {
377
+ title: {
378
+ en: "Phone Number",
379
+ uz: "Telefon Raqam",
380
+ ru: "Телефон номер"
381
+ },
382
+ type: "phone"
383
+ }
384
+ };
385
+
386
+ // Set active language
387
+ <ClientTable
388
+ schema={schema}
389
+ locale="uz" // Shows "Mijoz Ismi", "Telefon Raqam"
390
+ // ...
391
+ />
392
+ ```
393
+
394
+ ### Action Label Translations
395
+
396
+ ```typescript
397
+ const actionColumn = {
398
+ enable: true,
399
+ actions: [
400
+ {
401
+ title: {
402
+ en: "View Details",
403
+ uz: "Batafsil ko'rish",
404
+ ru: "Посмотреть детали"
405
+ },
406
+ onClick: "onView",
407
+ icon: "Eye"
408
+ }
409
+ ]
410
+ };
411
+ ```
110
412
 
111
413
  ## Customization
112
414
 
113
415
  ### Styles
114
416
 
417
+ Apply custom styles to different parts of the table:
418
+
115
419
  ```tsx
116
- import {
117
- AppsmithTable,
118
- AppsmithTableStyles,
119
- } from "@teamprodevs/appsmith-custom-table";
420
+ import { ClientTable } from "@teamprodevs/appsmith-custom-table";
421
+ import type { AppsmithTableStyles } from "@teamprodevs/appsmith-custom-table";
120
422
 
121
423
  const styles: AppsmithTableStyles = {
122
- table: "border border-gray-200 rounded-md",
123
- head: { cell: "bg-gray-50 text-gray-700 font-semibold" },
124
- body: { cell: "px-3 py-2" },
125
- footer: "bg-white border-t",
424
+ container: "bg-white shadow-md rounded-lg px-1",
425
+ table: "border border-gray-200",
426
+ head: {
427
+ body: "bg-gray-100",
428
+ row: "hover:bg-gray-200 transition-colors",
429
+ cell: "border-b border-gray-300 font-semibold"
430
+ },
431
+ body: {
432
+ body: "bg-white",
433
+ row: "odd:bg-gray-50 even:bg-white hover:bg-blue-50",
434
+ cell: "border-b border-gray-200 px-3 py-2"
435
+ }
126
436
  };
127
437
 
128
438
  const StyledTable = () => (
129
- <AppsmithTable schema={schema} data={data} styles={styles} />
439
+ <ClientTable
440
+ schema={schema}
441
+ tableData={data}
442
+ locale="en"
443
+ styles={styles}
444
+ // ...other props
445
+ />
130
446
  );
131
447
  ```
132
448
 
133
- ### Actions & Events
449
+ ### Style Options
450
+
451
+ | Option | Type | Description |
452
+ |--------|------|-------------|
453
+ | `container` | `string` | Wrapper container classes |
454
+ | `table` | `string` | Table element classes |
455
+ | `head.body` | `string` | Table header body classes |
456
+ | `head.row` | `string` | Header row classes |
457
+ | `head.cell` | `string` | Header cell classes |
458
+ | `body.body` | `string` | Table body classes |
459
+ | `body.row` | `string` | Body row classes |
460
+ | `body.cell` | `string` | Body cell classes |
461
+ | `variables` | `Record<string, string>` | CSS custom properties |
134
462
 
135
- - Define per-row action buttons or icons (edit, delete, open modal, etc.).
136
- - Trigger events with contextual payloads for Appsmith event handlers.
137
- - Consume `updateModel` to keep external state in sync with table interactions.
463
+ ### CSS Variables
138
464
 
139
- ## SSR Table Capabilities
465
+ Use CSS variables for theming with design tokens:
140
466
 
141
- - Works seamlessly with infinite-query patterns and cursor or offset pagination.
142
- - Handles server-driven sorting, filtering, and per-page controls.
143
- - Compatible with pgrest and dbtorest APIs out of the box.
144
- - Type-safe update flows ensure controlled mutations across distributed widgets.
467
+ ```typescript
468
+ const styles: AppsmithTableStyles = {
469
+ head: {
470
+ body: "bg-[var(--primary)] text-[var(--primary-foreground)]",
471
+ row: "hover:bg-[var(--primary-foreground)] hover:text-[var(--primary)]",
472
+ cell: "border-b border-[var(--border)]"
473
+ },
474
+ body: {
475
+ body: "bg-[var(--card)] text-[var(--card-foreground)]",
476
+ row: "odd:bg-[var(--accent)] even:bg-[var(--card)] hover:bg-[var(--muted)]",
477
+ cell: "border-b border-[var(--border)]"
478
+ },
479
+ container: "bg-[var(--card)] shadow-md rounded-lg px-1",
480
+ variables: {
481
+ "--primary": "hsl(220 70% 50%)",
482
+ "--primary-foreground": "hsl(0 0% 100%)",
483
+ "--card": "hsl(0 0% 100%)",
484
+ "--card-foreground": "hsl(0 0% 10%)",
485
+ "--border": "hsl(0 0% 90%)",
486
+ "--accent": "hsl(43 74% 66%)",
487
+ "--muted": "hsl(0 0% 96%)"
488
+ }
489
+ };
490
+ ```
145
491
 
146
- ## Client-Side Table Highlights
492
+ ### Index Column
147
493
 
148
- - Lightweight, in-memory data rendering with the same schema as SSR.
149
- - Perfect for Appsmith custom components shipped via CDN.
150
- - Supports local filtering, sorting, row selection, and inline actions without API calls.
494
+ Add a row index column:
495
+
496
+ ```typescript
497
+ const tableModel = {
498
+ // ...
499
+ indexColumn: {
500
+ enable: true,
501
+ pin: "left", // "left" | "right"
502
+ className: "bg-gray-100 font-mono"
503
+ }
504
+ };
505
+ ```
506
+
507
+ ## Events
508
+
509
+ The table triggers events through the `triggerEvent` callback:
510
+
511
+ | Event | Payload | Description |
512
+ |-------|---------|-------------|
513
+ | `onLoadMore` | `{ page, limit }` | Infinite scroll pagination request |
514
+ | `onRedirect` | `{ url }` | URL column click |
515
+ | `rowSelectionAction` | `{ row }` | Row selection (if configured) |
516
+ | Custom action events | `{ row }` | Row action button clicks |
517
+
518
+ ### Example Event Handling in Appsmith
519
+
520
+ ```javascript
521
+ // In your Appsmith custom widget
522
+ triggerEvent: (eventName, payload) => {
523
+ switch(eventName) {
524
+ case 'onView':
525
+ appsmith.triggerEvent('onRowView', { data: payload.row });
526
+ break;
527
+ case 'onEdit':
528
+ appsmith.triggerEvent('onRowEdit', { data: payload.row });
529
+ break;
530
+ case 'onDelete':
531
+ appsmith.triggerEvent('onRowDelete', { data: payload.row });
532
+ break;
533
+ case 'onLoadMore':
534
+ // Fetch next page
535
+ appsmith.triggerEvent('fetchNextPage', {
536
+ page: payload.page,
537
+ limit: payload.limit
538
+ });
539
+ break;
540
+ }
541
+ }
542
+ ```
543
+
544
+ ## Appsmith Integration
545
+
546
+ This table is designed for tight integration with Appsmith's ecosystem:
547
+
548
+ - **Data Sources**: Works with any Appsmith-supported data source (PostgreSQL, MongoDB, Elasticsearch, REST APIs, GraphQL)
549
+ - **Infinite Scroll**: Triggers `onLoadMore` events that you wire to Appsmith queries for pagination
550
+ - **Event System**: All actions flow through Appsmith's `triggerEvent` and `updateModel` APIs
551
+ - **Client-Side Rendering**: All rendering happens in the browser; Appsmith handles data fetching
552
+ - **pgrest/dbtorest Compatible**: Pagination parameters match common REST patterns
553
+
554
+ ### How It Works
555
+
556
+ 1. Your Appsmith query fetches data from any supported source
557
+ 2. Data is passed to `ClientTable` via the `tableData` prop
558
+ 3. User interactions trigger events (row clicks, actions, load more)
559
+ 4. You handle events in Appsmith to update queries or trigger workflows
560
+ 5. Updated data flows back to the table
151
561
 
152
562
  ## Development
153
563
 
@@ -156,18 +566,55 @@ const StyledTable = () => (
156
566
  3. Add stories, ensure lint/tests pass, then open a PR.
157
567
 
158
568
  ```bash
159
- git clone <your-fork>
569
+ git clone https://github.com/smarts-uz/appsmith-custom-table.git
160
570
  cd appsmith-custom-table
161
571
  npm install
162
572
  npm run storybook
163
573
  ```
164
574
 
575
+ ### Available Scripts
576
+
577
+ | Script | Description |
578
+ |--------|-------------|
579
+ | `npm run storybook` | Start Storybook dev server on port 6006 |
580
+ | `npm run build` | Build the library for production |
581
+ | `npm run build-storybook` | Build static Storybook site |
582
+ | `npm run lint` | Run ESLint |
583
+
165
584
  ## Contributing
166
585
 
167
- - Fork the repository and create a topic branch.
168
- - Add tests or stories that cover your changes.
169
- - Ensure formatting/lint pass, then submit a PR with context.
170
- - Please attribute inspiration to `tablecn`.
586
+ > ⚠️ **Note**: This project is not actively maintained. It was created as a job task to solve a specific problem. If you need new features or extended functionality, **please fork this repository** and develop your own version.
587
+
588
+ ### Forking This Project (Recommended)
589
+
590
+ Since this project is not actively maintained, forking is the recommended approach:
591
+
592
+ 1. **Fork the repository** — Click the ["Fork" button](https://github.com/smarts-uz/appsmith-custom-table/fork) on GitHub
593
+ 2. **Clone your fork**
594
+ ```bash
595
+ git clone https://github.com/YOUR_USERNAME/appsmith-custom-table.git
596
+ cd appsmith-custom-table
597
+ ```
598
+ 3. **Make it your own** — Add features, fix bugs, customize as needed
599
+ 4. **Publish your fork** — You can publish to npm under your own package name
600
+
601
+ ### Contributing Back (Critical Fixes Only)
602
+
603
+ For critical bug fixes that benefit everyone:
604
+
605
+ 1. Create a feature branch from your fork
606
+ 2. Make minimal, focused changes
607
+ 3. Run checks: `npm run lint && npm run build`
608
+ 4. Submit a PR with clear description
609
+
610
+ > **Note**: Response times may be slow and PRs may not be reviewed promptly.
611
+
612
+ ### Attribution
613
+
614
+ If you fork and extend this project, please:
615
+ - Keep the MIT license
616
+ - Credit the original `tablecn` project for inspiration
617
+ - Link back to this repository
171
618
 
172
619
  ## License
173
620
 
@@ -175,5 +622,7 @@ MIT © Ramz001
175
622
 
176
623
  ## Acknowledgements
177
624
 
178
- Huge thanks to the Appsmith community and the `tablecn` project for the foundational inspiration that sparked this library.
625
+ - Thanks to the Appsmith community for the platform that inspired this widget
626
+ - Thanks to the `tablecn` project for foundational inspiration
627
+ - This project was created as a job task at [Smarts](https://github.com/smarts-uz) to demonstrate Appsmith custom widget capabilities
179
628
 
package/dist/app.js CHANGED
@@ -40758,7 +40758,7 @@ function Uge(e) {
40758
40758
  m * l >= c && x(!1);
40759
40759
  }, [m, l, c]), he.useEffect(() => {
40760
40760
  w?.length > 0 && p((R) => {
40761
- R?.data?.length > 0 && R.data !== w && b(R.data || []);
40761
+ Array.isArray(R?.data) && R.data !== w && b(R.data || []);
40762
40762
  });
40763
40763
  }, [w]), y.success ? /* @__PURE__ */ L1(
40764
40764
  "main",
package/dist/app.umd.cjs CHANGED
@@ -64,4 +64,4 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
64
64
  .block-interactivity-`.concat(e,` {pointer-events: none;}
65
65
  .allow-interactivity-`).concat(e,` {pointer-events: all;}
66
66
  `)},CU=0,ei=[];function zU(e){var t=f.useRef([]),o=f.useRef([0,0]),a=f.useRef(),n=f.useState(CU++)[0],i=f.useState(_P)[0],c=f.useRef(e);f.useEffect(function(){c.current=e},[e]),f.useEffect(function(){if(e.inert){document.body.classList.add("block-interactivity-".concat(n));var _=YE([e.lockRef.current],(e.shards||[]).map(wP),!0).filter(Boolean);return _.forEach(function(m){return m.classList.add("allow-interactivity-".concat(n))}),function(){document.body.classList.remove("block-interactivity-".concat(n)),_.forEach(function(m){return m.classList.remove("allow-interactivity-".concat(n))})}}},[e.inert,e.lockRef.current,e.shards]);var d=f.useCallback(function(_,m){if("touches"in _&&_.touches.length===2||_.type==="wheel"&&_.ctrlKey)return!c.current.allowPinchZoom;var g=ab(_),w=o.current,$="deltaX"in _?_.deltaX:w[0]-g[0],b="deltaY"in _?_.deltaY:w[1]-g[1],N,P=_.target,C=Math.abs($)>Math.abs(b)?"h":"v";if("touches"in _&&C==="h"&&P.type==="range")return!1;var I=gP(C,P);if(!I)return!0;if(I?N=C:(N=C==="v"?"h":"v",I=gP(C,P)),!I)return!1;if(!a.current&&"changedTouches"in _&&($||b)&&(a.current=N),!N)return!0;var T=a.current||N;return IU(T,m,_,T==="h"?$:b)},[]),l=f.useCallback(function(_){var m=_;if(!(!ei.length||ei[ei.length-1]!==i)){var g="deltaY"in m?$P(m):ab(m),w=t.current.filter(function(N){return N.name===m.type&&(N.target===m.target||m.target===N.shadowParent)&&LU(N.delta,g)})[0];if(w&&w.should){m.cancelable&&m.preventDefault();return}if(!w){var $=(c.current.shards||[]).map(wP).filter(Boolean).filter(function(N){return N.contains(m.target)}),b=$.length>0?d(m,$[0]):!c.current.noIsolation;b&&m.cancelable&&m.preventDefault()}}},[]),s=f.useCallback(function(_,m,g,w){var $={name:_,delta:m,target:g,should:w,shadowParent:AU(g)};t.current.push($),setTimeout(function(){t.current=t.current.filter(function(b){return b!==$})},1)},[]),u=f.useCallback(function(_){o.current=ab(_),a.current=void 0},[]),h=f.useCallback(function(_){s(_.type,$P(_),_.target,d(_,e.lockRef.current))},[]),k=f.useCallback(function(_){s(_.type,ab(_),_.target,d(_,e.lockRef.current))},[]);f.useEffect(function(){return ei.push(i),e.setCallbacks({onScrollCapture:h,onWheelCapture:h,onTouchMoveCapture:k}),document.addEventListener("wheel",l,Q1),document.addEventListener("touchmove",l,Q1),document.addEventListener("touchstart",u,Q1),function(){ei=ei.filter(function(_){return _!==i}),document.removeEventListener("wheel",l,Q1),document.removeEventListener("touchmove",l,Q1),document.removeEventListener("touchstart",u,Q1)}},[]);var p=e.removeScrollBar,y=e.inert;return f.createElement(f.Fragment,null,y?f.createElement(i,{styles:SU(n)}):null,p?f.createElement(vU,{noRelative:e.noRelative,gapMode:e.gapMode}):null)}function AU(e){for(var t=null;e!==null;)e instanceof ShadowRoot&&(t=e.host,e=e.host),e=e.parentNode;return t}const jU=cU(kP,zU);var QN=f.forwardRef(function(e,t){return f.createElement(nb,Be({},e,{ref:t,sideCar:jU}))});QN.classNames=nb.classNames;var eI=["Enter"," "],PU=["ArrowDown","PageUp","Home"],bP=["ArrowUp","PageDown","End"],qU=[...PU,...bP],DU={ltr:[...eI,"ArrowRight"],rtl:[...eI,"ArrowLeft"]},OU={ltr:["ArrowLeft"],rtl:["ArrowRight"]},Pi="Menu",[qi,HU,VU]=lj(Pi),[P1,xP]=Z1(Pi,[VU,Xw,iP]),ib=Xw(),NP=iP(),[RU,q1]=P1(Pi),[TU,Di]=P1(Pi),IP=e=>{const{__scopeMenu:t,open:o=!1,children:a,dir:n,onOpenChange:i,modal:c=!0}=e,d=ib(t),[l,s]=f.useState(null),u=f.useRef(!1),h=et(i),k=uj(n);return f.useEffect(()=>{const p=()=>{u.current=!0,document.addEventListener("pointerdown",y,{capture:!0,once:!0}),document.addEventListener("pointermove",y,{capture:!0,once:!0})},y=()=>u.current=!1;return document.addEventListener("keydown",p,{capture:!0}),()=>{document.removeEventListener("keydown",p,{capture:!0}),document.removeEventListener("pointerdown",y,{capture:!0}),document.removeEventListener("pointermove",y,{capture:!0})}},[]),M.jsx(tP,{...d,children:M.jsx(RU,{scope:t,open:o,onOpenChange:h,content:l,onContentChange:s,children:M.jsx(TU,{scope:t,onClose:f.useCallback(()=>h(!1),[h]),isUsingKeyboardRef:u,dir:k,modal:c,children:a})})})};IP.displayName=Pi;var FU="MenuAnchor",tI=f.forwardRef((e,t)=>{const{__scopeMenu:o,...a}=e,n=ib(o);return M.jsx(UN,{...n,...a,ref:t})});tI.displayName=FU;var nI="MenuPortal",[EU,LP]=P1(nI,{forceMount:void 0}),SP=e=>{const{__scopeMenu:t,forceMount:o,children:a,container:n}=e,i=q1(nI,t);return M.jsx(EU,{scope:t,forceMount:o,children:M.jsx(j1,{present:o||i.open,children:M.jsx(BN,{asChild:!0,container:n,children:a})})})};SP.displayName=nI;var be="MenuContent",[UU,oI]=P1(be),CP=f.forwardRef((e,t)=>{const o=LP(be,e.__scopeMenu),{forceMount:a=o.forceMount,...n}=e,i=q1(be,e.__scopeMenu),c=Di(be,e.__scopeMenu);return M.jsx(qi.Provider,{scope:e.__scopeMenu,children:M.jsx(j1,{present:a||i.open,children:M.jsx(qi.Slot,{scope:e.__scopeMenu,children:c.modal?M.jsx(BU,{...n,ref:t}):M.jsx(ZU,{...n,ref:t})})})})}),BU=f.forwardRef((e,t)=>{const o=q1(be,e.__scopeMenu),a=f.useRef(null),n=ue(t,a);return f.useEffect(()=>{const i=a.current;if(i)return uP(i)},[]),M.jsx(aI,{...e,ref:n,trapFocus:o.open,disableOutsidePointerEvents:o.open,disableOutsideScroll:!0,onFocusOutside:U(e.onFocusOutside,i=>i.preventDefault(),{checkForDefaultPrevented:!1}),onDismiss:()=>o.onOpenChange(!1)})}),ZU=f.forwardRef((e,t)=>{const o=q1(be,e.__scopeMenu);return M.jsx(aI,{...e,ref:t,trapFocus:!1,disableOutsidePointerEvents:!1,disableOutsideScroll:!1,onDismiss:()=>o.onOpenChange(!1)})}),GU=Si("MenuContent.ScrollLock"),aI=f.forwardRef((e,t)=>{const{__scopeMenu:o,loop:a=!1,trapFocus:n,onOpenAutoFocus:i,onCloseAutoFocus:c,disableOutsidePointerEvents:d,onEntryFocus:l,onEscapeKeyDown:s,onPointerDownOutside:u,onFocusOutside:h,onInteractOutside:k,onDismiss:p,disableOutsideScroll:y,..._}=e,m=q1(be,o),g=Di(be,o),w=ib(o),$=NP(o),b=HU(o),[N,P]=f.useState(null),C=f.useRef(null),I=ue(t,C,m.onContentChange),T=f.useRef(0),D=f.useRef(""),Z=f.useRef(0),X=f.useRef(null),J=f.useRef("right"),K=f.useRef(0),oe=y?QN:f.Fragment,B=y?{as:GU,allowPinchZoom:!0}:void 0,Y=q=>{const re=D.current+q,$e=b().filter(G=>!G.disabled),Ae=document.activeElement,ie=$e.find(G=>G.ref.current===Ae)?.textValue,de=$e.map(G=>G.textValue),ot=iB(de,re,ie),Ze=$e.find(G=>G.textValue===ot)?.ref.current;(function G(kt){D.current=kt,window.clearTimeout(T.current),kt!==""&&(T.current=window.setTimeout(()=>G(""),1e3))})(re),Ze&&setTimeout(()=>Ze.focus())};f.useEffect(()=>()=>window.clearTimeout(T.current),[]),_j();const S=f.useCallback(q=>J.current===X.current?.side&&cB(q,X.current?.area),[]);return M.jsx(UU,{scope:o,searchRef:D,onItemEnter:f.useCallback(q=>{S(q)&&q.preventDefault()},[S]),onItemLeave:f.useCallback(q=>{S(q)||(C.current?.focus(),P(null))},[S]),onTriggerLeave:f.useCallback(q=>{S(q)&&q.preventDefault()},[S]),pointerGraceTimerRef:Z,onPointerGraceIntentChange:f.useCallback(q=>{X.current=q},[]),children:M.jsx(oe,{...B,children:M.jsx(CN,{asChild:!0,trapped:n,onMountAutoFocus:U(i,q=>{q.preventDefault(),C.current?.focus({preventScroll:!0})}),onUnmountAutoFocus:c,children:M.jsx(NN,{asChild:!0,disableOutsidePointerEvents:d,onEscapeKeyDown:s,onPointerDownOutside:u,onFocusOutside:h,onInteractOutside:k,onDismiss:p,children:M.jsx(GE,{asChild:!0,...$,dir:g.dir,orientation:"vertical",loop:a,currentTabStopId:N,onCurrentTabStopIdChange:P,onEntryFocus:U(l,q=>{g.isUsingKeyboardRef.current||q.preventDefault()}),preventScrollOnEntryFocus:!0,children:M.jsx(nP,{role:"menu","aria-orientation":"vertical","data-state":GP(m.open),"data-radix-menu-content":"",dir:g.dir,...w,..._,ref:I,style:{outline:"none",..._.style},onKeyDown:U(_.onKeyDown,q=>{const $e=q.target.closest("[data-radix-menu-content]")===q.currentTarget,Ae=q.ctrlKey||q.altKey||q.metaKey,ie=q.key.length===1;$e&&(q.key==="Tab"&&q.preventDefault(),!Ae&&ie&&Y(q.key));const de=C.current;if(q.target!==de||!qU.includes(q.key))return;q.preventDefault();const Ze=b().filter(G=>!G.disabled).map(G=>G.ref.current);bP.includes(q.key)&&Ze.reverse(),oB(Ze)}),onBlur:U(e.onBlur,q=>{q.currentTarget.contains(q.target)||(window.clearTimeout(T.current),D.current="")}),onPointerMove:U(e.onPointerMove,Hi(q=>{const re=q.target,$e=K.current!==q.clientX;if(q.currentTarget.contains(re)&&$e){const Ae=q.clientX>K.current?"right":"left";J.current=Ae,K.current=q.clientX}}))})})})})})})});CP.displayName=be;var WU="MenuGroup",iI=f.forwardRef((e,t)=>{const{__scopeMenu:o,...a}=e;return M.jsx(se.div,{role:"group",...a,ref:t})});iI.displayName=WU;var KU="MenuLabel",zP=f.forwardRef((e,t)=>{const{__scopeMenu:o,...a}=e;return M.jsx(se.div,{...a,ref:t})});zP.displayName=KU;var rb="MenuItem",AP="menu.itemSelect",cb=f.forwardRef((e,t)=>{const{disabled:o=!1,onSelect:a,...n}=e,i=f.useRef(null),c=Di(rb,e.__scopeMenu),d=oI(rb,e.__scopeMenu),l=ue(t,i),s=f.useRef(!1),u=()=>{const h=i.current;if(!o&&h){const k=new CustomEvent(AP,{bubbles:!0,cancelable:!0});h.addEventListener(AP,p=>a?.(p),{once:!0}),sj(h,k),k.defaultPrevented?s.current=!1:c.onClose()}};return M.jsx(jP,{...n,ref:l,disabled:o,onClick:U(e.onClick,u),onPointerDown:h=>{e.onPointerDown?.(h),s.current=!0},onPointerUp:U(e.onPointerUp,h=>{s.current||h.currentTarget?.click()}),onKeyDown:U(e.onKeyDown,h=>{const k=d.searchRef.current!=="";o||k&&h.key===" "||eI.includes(h.key)&&(h.currentTarget.click(),h.preventDefault())})})});cb.displayName=rb;var jP=f.forwardRef((e,t)=>{const{__scopeMenu:o,disabled:a=!1,textValue:n,...i}=e,c=oI(rb,o),d=NP(o),l=f.useRef(null),s=ue(t,l),[u,h]=f.useState(!1),[k,p]=f.useState("");return f.useEffect(()=>{const y=l.current;y&&p((y.textContent??"").trim())},[i.children]),M.jsx(qi.ItemSlot,{scope:o,disabled:a,textValue:n??k,children:M.jsx(WE,{asChild:!0,...d,focusable:!a,children:M.jsx(se.div,{role:"menuitem","data-highlighted":u?"":void 0,"aria-disabled":a||void 0,"data-disabled":a?"":void 0,...i,ref:s,onPointerMove:U(e.onPointerMove,Hi(y=>{a?c.onItemLeave(y):(c.onItemEnter(y),y.defaultPrevented||y.currentTarget.focus({preventScroll:!0}))})),onPointerLeave:U(e.onPointerLeave,Hi(y=>c.onItemLeave(y))),onFocus:U(e.onFocus,()=>h(!0)),onBlur:U(e.onBlur,()=>h(!1))})})})}),XU="MenuCheckboxItem",PP=f.forwardRef((e,t)=>{const{checked:o=!1,onCheckedChange:a,...n}=e;return M.jsx(VP,{scope:e.__scopeMenu,checked:o,children:M.jsx(cb,{role:"menuitemcheckbox","aria-checked":db(o)?"mixed":o,...n,ref:t,"data-state":cI(o),onSelect:U(n.onSelect,()=>a?.(db(o)?!0:!o),{checkForDefaultPrevented:!1})})})});PP.displayName=XU;var qP="MenuRadioGroup",[JU,YU]=P1(qP,{value:void 0,onValueChange:()=>{}}),DP=f.forwardRef((e,t)=>{const{value:o,onValueChange:a,...n}=e,i=et(a);return M.jsx(JU,{scope:e.__scopeMenu,value:o,onValueChange:i,children:M.jsx(iI,{...n,ref:t})})});DP.displayName=qP;var OP="MenuRadioItem",HP=f.forwardRef((e,t)=>{const{value:o,...a}=e,n=YU(OP,e.__scopeMenu),i=o===n.value;return M.jsx(VP,{scope:e.__scopeMenu,checked:i,children:M.jsx(cb,{role:"menuitemradio","aria-checked":i,...a,ref:t,"data-state":cI(i),onSelect:U(a.onSelect,()=>n.onValueChange?.(o),{checkForDefaultPrevented:!1})})})});HP.displayName=OP;var rI="MenuItemIndicator",[VP,QU]=P1(rI,{checked:!1}),RP=f.forwardRef((e,t)=>{const{__scopeMenu:o,forceMount:a,...n}=e,i=QU(rI,o);return M.jsx(j1,{present:a||db(i.checked)||i.checked===!0,children:M.jsx(se.span,{...n,ref:t,"data-state":cI(i.checked)})})});RP.displayName=rI;var eB="MenuSeparator",TP=f.forwardRef((e,t)=>{const{__scopeMenu:o,...a}=e;return M.jsx(se.div,{role:"separator","aria-orientation":"horizontal",...a,ref:t})});TP.displayName=eB;var tB="MenuArrow",FP=f.forwardRef((e,t)=>{const{__scopeMenu:o,...a}=e,n=ib(o);return M.jsx(oP,{...n,...a,ref:t})});FP.displayName=tB;var nB="MenuSub",[qme,EP]=P1(nB),Oi="MenuSubTrigger",UP=f.forwardRef((e,t)=>{const o=q1(Oi,e.__scopeMenu),a=Di(Oi,e.__scopeMenu),n=EP(Oi,e.__scopeMenu),i=oI(Oi,e.__scopeMenu),c=f.useRef(null),{pointerGraceTimerRef:d,onPointerGraceIntentChange:l}=i,s={__scopeMenu:e.__scopeMenu},u=f.useCallback(()=>{c.current&&window.clearTimeout(c.current),c.current=null},[]);return f.useEffect(()=>u,[u]),f.useEffect(()=>{const h=d.current;return()=>{window.clearTimeout(h),l(null)}},[d,l]),M.jsx(tI,{asChild:!0,...s,children:M.jsx(jP,{id:n.triggerId,"aria-haspopup":"menu","aria-expanded":o.open,"aria-controls":n.contentId,"data-state":GP(o.open),...e,ref:Li(t,n.onTriggerChange),onClick:h=>{e.onClick?.(h),!(e.disabled||h.defaultPrevented)&&(h.currentTarget.focus(),o.open||o.onOpenChange(!0))},onPointerMove:U(e.onPointerMove,Hi(h=>{i.onItemEnter(h),!h.defaultPrevented&&!e.disabled&&!o.open&&!c.current&&(i.onPointerGraceIntentChange(null),c.current=window.setTimeout(()=>{o.onOpenChange(!0),u()},100))})),onPointerLeave:U(e.onPointerLeave,Hi(h=>{u();const k=o.content?.getBoundingClientRect();if(k){const p=o.content?.dataset.side,y=p==="right",_=y?-5:5,m=k[y?"left":"right"],g=k[y?"right":"left"];i.onPointerGraceIntentChange({area:[{x:h.clientX+_,y:h.clientY},{x:m,y:k.top},{x:g,y:k.top},{x:g,y:k.bottom},{x:m,y:k.bottom}],side:p}),window.clearTimeout(d.current),d.current=window.setTimeout(()=>i.onPointerGraceIntentChange(null),300)}else{if(i.onTriggerLeave(h),h.defaultPrevented)return;i.onPointerGraceIntentChange(null)}})),onKeyDown:U(e.onKeyDown,h=>{const k=i.searchRef.current!=="";e.disabled||k&&h.key===" "||DU[a.dir].includes(h.key)&&(o.onOpenChange(!0),o.content?.focus(),h.preventDefault())})})})});UP.displayName=Oi;var BP="MenuSubContent",ZP=f.forwardRef((e,t)=>{const o=LP(be,e.__scopeMenu),{forceMount:a=o.forceMount,...n}=e,i=q1(be,e.__scopeMenu),c=Di(be,e.__scopeMenu),d=EP(BP,e.__scopeMenu),l=f.useRef(null),s=ue(t,l);return M.jsx(qi.Provider,{scope:e.__scopeMenu,children:M.jsx(j1,{present:a||i.open,children:M.jsx(qi.Slot,{scope:e.__scopeMenu,children:M.jsx(aI,{id:d.contentId,"aria-labelledby":d.triggerId,...n,ref:s,align:"start",side:c.dir==="rtl"?"left":"right",disableOutsidePointerEvents:!1,disableOutsideScroll:!1,trapFocus:!1,onOpenAutoFocus:u=>{c.isUsingKeyboardRef.current&&l.current?.focus(),u.preventDefault()},onCloseAutoFocus:u=>u.preventDefault(),onFocusOutside:U(e.onFocusOutside,u=>{u.target!==d.trigger&&i.onOpenChange(!1)}),onEscapeKeyDown:U(e.onEscapeKeyDown,u=>{c.onClose(),u.preventDefault()}),onKeyDown:U(e.onKeyDown,u=>{const h=u.currentTarget.contains(u.target),k=OU[c.dir].includes(u.key);h&&k&&(i.onOpenChange(!1),d.trigger?.focus(),u.preventDefault())})})})})})});ZP.displayName=BP;function GP(e){return e?"open":"closed"}function db(e){return e==="indeterminate"}function cI(e){return db(e)?"indeterminate":e?"checked":"unchecked"}function oB(e){const t=document.activeElement;for(const o of e)if(o===t||(o.focus(),document.activeElement!==t))return}function aB(e,t){return e.map((o,a)=>e[(t+a)%e.length])}function iB(e,t,o){const n=t.length>1&&Array.from(t).every(s=>s===t[0])?t[0]:t,i=o?e.indexOf(o):-1;let c=aB(e,Math.max(i,0));n.length===1&&(c=c.filter(s=>s!==o));const l=c.find(s=>s.toLowerCase().startsWith(n.toLowerCase()));return l!==o?l:void 0}function rB(e,t){const{x:o,y:a}=e;let n=!1;for(let i=0,c=t.length-1;i<t.length;c=i++){const d=t[i],l=t[c],s=d.x,u=d.y,h=l.x,k=l.y;u>a!=k>a&&o<(h-s)*(a-u)/(k-u)+s&&(n=!n)}return n}function cB(e,t){if(!t)return!1;const o={x:e.clientX,y:e.clientY};return rB(o,t)}function Hi(e){return t=>t.pointerType==="mouse"?e(t):void 0}var dB=IP,sB=tI,lB=SP,uB=CP,hB=iI,pB=zP,yB=cb,kB=PP,_B=DP,fB=HP,mB=RP,gB=TP,vB=FP,MB=UP,$B=ZP,sb="DropdownMenu",[wB]=Z1(sb,[xP]),ye=xP(),[bB,WP]=wB(sb),KP=e=>{const{__scopeDropdownMenu:t,children:o,dir:a,open:n,defaultOpen:i,onOpenChange:c,modal:d=!0}=e,l=ye(t),s=f.useRef(null),[u,h]=bN({prop:n,defaultProp:i??!1,onChange:c,caller:sb});return M.jsx(bB,{scope:t,triggerId:Vw(),triggerRef:s,contentId:Vw(),open:u,onOpenChange:h,onOpenToggle:f.useCallback(()=>h(k=>!k),[h]),modal:d,children:M.jsx(dB,{...l,open:u,onOpenChange:h,dir:a,modal:d,children:o})})};KP.displayName=sb;var XP="DropdownMenuTrigger",JP=f.forwardRef((e,t)=>{const{__scopeDropdownMenu:o,disabled:a=!1,...n}=e,i=WP(XP,o),c=ye(o);return M.jsx(sB,{asChild:!0,...c,children:M.jsx(se.button,{type:"button",id:i.triggerId,"aria-haspopup":"menu","aria-expanded":i.open,"aria-controls":i.open?i.contentId:void 0,"data-state":i.open?"open":"closed","data-disabled":a?"":void 0,disabled:a,...n,ref:Li(t,i.triggerRef),onPointerDown:U(e.onPointerDown,d=>{!a&&d.button===0&&d.ctrlKey===!1&&(i.onOpenToggle(),i.open||d.preventDefault())}),onKeyDown:U(e.onKeyDown,d=>{a||(["Enter"," "].includes(d.key)&&i.onOpenToggle(),d.key==="ArrowDown"&&i.onOpenChange(!0),["Enter"," ","ArrowDown"].includes(d.key)&&d.preventDefault())})})})});JP.displayName=XP;var xB="DropdownMenuPortal",YP=e=>{const{__scopeDropdownMenu:t,...o}=e,a=ye(t);return M.jsx(lB,{...a,...o})};YP.displayName=xB;var QP="DropdownMenuContent",eq=f.forwardRef((e,t)=>{const{__scopeDropdownMenu:o,...a}=e,n=WP(QP,o),i=ye(o),c=f.useRef(!1);return M.jsx(uB,{id:n.contentId,"aria-labelledby":n.triggerId,...i,...a,ref:t,onCloseAutoFocus:U(e.onCloseAutoFocus,d=>{c.current||n.triggerRef.current?.focus(),c.current=!1,d.preventDefault()}),onInteractOutside:U(e.onInteractOutside,d=>{const l=d.detail.originalEvent,s=l.button===0&&l.ctrlKey===!0,u=l.button===2||s;(!n.modal||u)&&(c.current=!0)}),style:{...e.style,"--radix-dropdown-menu-content-transform-origin":"var(--radix-popper-transform-origin)","--radix-dropdown-menu-content-available-width":"var(--radix-popper-available-width)","--radix-dropdown-menu-content-available-height":"var(--radix-popper-available-height)","--radix-dropdown-menu-trigger-width":"var(--radix-popper-anchor-width)","--radix-dropdown-menu-trigger-height":"var(--radix-popper-anchor-height)"}})});eq.displayName=QP;var NB="DropdownMenuGroup",IB=f.forwardRef((e,t)=>{const{__scopeDropdownMenu:o,...a}=e,n=ye(o);return M.jsx(hB,{...n,...a,ref:t})});IB.displayName=NB;var LB="DropdownMenuLabel",SB=f.forwardRef((e,t)=>{const{__scopeDropdownMenu:o,...a}=e,n=ye(o);return M.jsx(pB,{...n,...a,ref:t})});SB.displayName=LB;var CB="DropdownMenuItem",tq=f.forwardRef((e,t)=>{const{__scopeDropdownMenu:o,...a}=e,n=ye(o);return M.jsx(yB,{...n,...a,ref:t})});tq.displayName=CB;var zB="DropdownMenuCheckboxItem",AB=f.forwardRef((e,t)=>{const{__scopeDropdownMenu:o,...a}=e,n=ye(o);return M.jsx(kB,{...n,...a,ref:t})});AB.displayName=zB;var jB="DropdownMenuRadioGroup",PB=f.forwardRef((e,t)=>{const{__scopeDropdownMenu:o,...a}=e,n=ye(o);return M.jsx(_B,{...n,...a,ref:t})});PB.displayName=jB;var qB="DropdownMenuRadioItem",DB=f.forwardRef((e,t)=>{const{__scopeDropdownMenu:o,...a}=e,n=ye(o);return M.jsx(fB,{...n,...a,ref:t})});DB.displayName=qB;var OB="DropdownMenuItemIndicator",HB=f.forwardRef((e,t)=>{const{__scopeDropdownMenu:o,...a}=e,n=ye(o);return M.jsx(mB,{...n,...a,ref:t})});HB.displayName=OB;var VB="DropdownMenuSeparator",RB=f.forwardRef((e,t)=>{const{__scopeDropdownMenu:o,...a}=e,n=ye(o);return M.jsx(gB,{...n,...a,ref:t})});RB.displayName=VB;var TB="DropdownMenuArrow",FB=f.forwardRef((e,t)=>{const{__scopeDropdownMenu:o,...a}=e,n=ye(o);return M.jsx(vB,{...n,...a,ref:t})});FB.displayName=TB;var EB="DropdownMenuSubTrigger",UB=f.forwardRef((e,t)=>{const{__scopeDropdownMenu:o,...a}=e,n=ye(o);return M.jsx(MB,{...n,...a,ref:t})});UB.displayName=EB;var BB="DropdownMenuSubContent",ZB=f.forwardRef((e,t)=>{const{__scopeDropdownMenu:o,...a}=e,n=ye(o);return M.jsx($B,{...n,...a,ref:t,style:{...e.style,"--radix-dropdown-menu-content-transform-origin":"var(--radix-popper-transform-origin)","--radix-dropdown-menu-content-available-width":"var(--radix-popper-available-width)","--radix-dropdown-menu-content-available-height":"var(--radix-popper-available-height)","--radix-dropdown-menu-trigger-width":"var(--radix-popper-anchor-width)","--radix-dropdown-menu-trigger-height":"var(--radix-popper-anchor-height)"}})});ZB.displayName=BB;var GB=KP,WB=JP,KB=YP,XB=eq,JB=tq;function YB({...e}){return M.jsx(GB,{"data-slot":"dropdown-menu",...e})}function QB({...e}){return M.jsx(WB,{"data-slot":"dropdown-menu-trigger",...e})}function eZ({className:e,sideOffset:t=4,...o}){return M.jsx(KB,{children:M.jsx(XB,{"data-slot":"dropdown-menu-content",sideOffset:t,className:ae("bg-popover text-popover-foreground data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0 data-[state=closed]:zoom-out-95 data-[state=open]:zoom-in-95 data-[side=bottom]:slide-in-from-top-2 data-[side=left]:slide-in-from-right-2 data-[side=right]:slide-in-from-left-2 data-[side=top]:slide-in-from-bottom-2 z-50 max-h-(--radix-dropdown-menu-content-available-height) min-w-[8rem] origin-(--radix-dropdown-menu-content-transform-origin) overflow-x-hidden overflow-y-auto rounded-md border p-1 shadow-md",e),...o})})}function tZ({className:e,inset:t,variant:o="default",...a}){return M.jsx(JB,{"data-slot":"dropdown-menu-item","data-inset":t,"data-variant":o,className:ae("focus:bg-accent focus:text-accent-foreground data-[variant=destructive]:text-destructive data-[variant=destructive]:focus:bg-destructive/10 dark:data-[variant=destructive]:focus:bg-destructive/20 data-[variant=destructive]:focus:text-destructive data-[variant=destructive]:*:[svg]:!text-destructive [&_svg:not([class*='text-'])]:text-muted-foreground relative flex cursor-default items-center gap-2 rounded-sm px-2 py-1.5 text-sm outline-hidden select-none data-[disabled]:pointer-events-none data-[disabled]:opacity-50 data-[inset]:pl-8 [&_svg]:pointer-events-none [&_svg]:shrink-0 [&_svg:not([class*='size-'])]:size-4",e),...a})}function nZ({row:e,type:t,actionColumn:o,triggerEvent:a,locale:n,updateModel:i}){const c=(s,u)=>{u.stopPropagation(),a&&a(s,{row:e.original}),i&&i({triggeredRow:e.original})},d=o?.actions?.length===1,l=s=>{const u=s&&Ow[s]?Ow[s]:Ni;return M.jsx(u,{className:"w-5 h-5 text-inherit"})};if(e.original?.__empty)return null;if(d){const s=o?.actions[0];return M.jsx(dj,{variant:t||"default",size:"icon",className:ae("w-full min-w-8 h-full p-2 flex items-center gap-2",s?.className),onClick:u=>c(s.onClick,u),children:l(s.icon)})}return M.jsxs(YB,{children:[M.jsx(QB,{children:M.jsx(dj,{asChild:!0,size:"icon",variant:t||"default",className:"w-full h-full p-2 min-w-8 mx-auto",children:l(o?.icon||"MoreHorizontal")})}),M.jsx(eZ,{align:"end",className:"w-64",children:o?.actions?.map((s,u)=>M.jsxs(tZ,{className:ae("flex items-center gap-2 text-base font-semibold",s?.className),onClick:h=>c(s.onClick,h),children:[l(s.icon),s.title[n]]},u))})]})}var lb="Popover",[nq]=Z1(lb,[Xw]),Vi=Xw(),[oZ,yt]=nq(lb),oq=e=>{const{__scopePopover:t,children:o,open:a,defaultOpen:n,onOpenChange:i,modal:c=!1}=e,d=Vi(t),l=f.useRef(null),[s,u]=f.useState(!1),[h,k]=bN({prop:a,defaultProp:n??!1,onChange:i,caller:lb});return M.jsx(tP,{...d,children:M.jsx(oZ,{scope:t,contentId:Vw(),triggerRef:l,open:h,onOpenChange:k,onOpenToggle:f.useCallback(()=>k(p=>!p),[k]),hasCustomAnchor:s,onCustomAnchorAdd:f.useCallback(()=>u(!0),[]),onCustomAnchorRemove:f.useCallback(()=>u(!1),[]),modal:c,children:o})})};oq.displayName=lb;var aq="PopoverAnchor",aZ=f.forwardRef((e,t)=>{const{__scopePopover:o,...a}=e,n=yt(aq,o),i=Vi(o),{onCustomAnchorAdd:c,onCustomAnchorRemove:d}=n;return f.useEffect(()=>(c(),()=>d()),[c,d]),M.jsx(UN,{...i,...a,ref:t})});aZ.displayName=aq;var iq="PopoverTrigger",rq=f.forwardRef((e,t)=>{const{__scopePopover:o,...a}=e,n=yt(iq,o),i=Vi(o),c=ue(t,n.triggerRef),d=M.jsx(se.button,{type:"button","aria-haspopup":"dialog","aria-expanded":n.open,"aria-controls":n.contentId,"data-state":uq(n.open),...a,ref:c,onClick:U(e.onClick,n.onOpenToggle)});return n.hasCustomAnchor?d:M.jsx(UN,{asChild:!0,...i,children:d})});rq.displayName=iq;var dI="PopoverPortal",[iZ,rZ]=nq(dI,{forceMount:void 0}),cq=e=>{const{__scopePopover:t,forceMount:o,children:a,container:n}=e,i=yt(dI,t);return M.jsx(iZ,{scope:t,forceMount:o,children:M.jsx(j1,{present:o||i.open,children:M.jsx(BN,{asChild:!0,container:n,children:a})})})};cq.displayName=dI;var ti="PopoverContent",dq=f.forwardRef((e,t)=>{const o=rZ(ti,e.__scopePopover),{forceMount:a=o.forceMount,...n}=e,i=yt(ti,e.__scopePopover);return M.jsx(j1,{present:a||i.open,children:i.modal?M.jsx(dZ,{...n,ref:t}):M.jsx(sZ,{...n,ref:t})})});dq.displayName=ti;var cZ=Si("PopoverContent.RemoveScroll"),dZ=f.forwardRef((e,t)=>{const o=yt(ti,e.__scopePopover),a=f.useRef(null),n=ue(t,a),i=f.useRef(!1);return f.useEffect(()=>{const c=a.current;if(c)return uP(c)},[]),M.jsx(QN,{as:cZ,allowPinchZoom:!0,children:M.jsx(sq,{...e,ref:n,trapFocus:o.open,disableOutsidePointerEvents:!0,onCloseAutoFocus:U(e.onCloseAutoFocus,c=>{c.preventDefault(),i.current||o.triggerRef.current?.focus()}),onPointerDownOutside:U(e.onPointerDownOutside,c=>{const d=c.detail.originalEvent,l=d.button===0&&d.ctrlKey===!0,s=d.button===2||l;i.current=s},{checkForDefaultPrevented:!1}),onFocusOutside:U(e.onFocusOutside,c=>c.preventDefault(),{checkForDefaultPrevented:!1})})})}),sZ=f.forwardRef((e,t)=>{const o=yt(ti,e.__scopePopover),a=f.useRef(!1),n=f.useRef(!1);return M.jsx(sq,{...e,ref:t,trapFocus:!1,disableOutsidePointerEvents:!1,onCloseAutoFocus:i=>{e.onCloseAutoFocus?.(i),i.defaultPrevented||(a.current||o.triggerRef.current?.focus(),i.preventDefault()),a.current=!1,n.current=!1},onInteractOutside:i=>{e.onInteractOutside?.(i),i.defaultPrevented||(a.current=!0,i.detail.originalEvent.type==="pointerdown"&&(n.current=!0));const c=i.target;o.triggerRef.current?.contains(c)&&i.preventDefault(),i.detail.originalEvent.type==="focusin"&&n.current&&i.preventDefault()}})}),sq=f.forwardRef((e,t)=>{const{__scopePopover:o,trapFocus:a,onOpenAutoFocus:n,onCloseAutoFocus:i,disableOutsidePointerEvents:c,onEscapeKeyDown:d,onPointerDownOutside:l,onFocusOutside:s,onInteractOutside:u,...h}=e,k=yt(ti,o),p=Vi(o);return _j(),M.jsx(CN,{asChild:!0,loop:!0,trapped:a,onMountAutoFocus:n,onUnmountAutoFocus:i,children:M.jsx(NN,{asChild:!0,disableOutsidePointerEvents:c,onInteractOutside:u,onEscapeKeyDown:d,onPointerDownOutside:l,onFocusOutside:s,onDismiss:()=>k.onOpenChange(!1),children:M.jsx(nP,{"data-state":uq(k.open),role:"dialog",id:k.contentId,...p,...h,ref:t,style:{...h.style,"--radix-popover-content-transform-origin":"var(--radix-popper-transform-origin)","--radix-popover-content-available-width":"var(--radix-popper-available-width)","--radix-popover-content-available-height":"var(--radix-popper-available-height)","--radix-popover-trigger-width":"var(--radix-popper-anchor-width)","--radix-popover-trigger-height":"var(--radix-popper-anchor-height)"}})})})}),lq="PopoverClose",lZ=f.forwardRef((e,t)=>{const{__scopePopover:o,...a}=e,n=yt(lq,o);return M.jsx(se.button,{type:"button",...a,ref:t,onClick:U(e.onClick,()=>n.onOpenChange(!1))})});lZ.displayName=lq;var uZ="PopoverArrow",hZ=f.forwardRef((e,t)=>{const{__scopePopover:o,...a}=e,n=Vi(o);return M.jsx(oP,{...n,...a,ref:t})});hZ.displayName=uZ;function uq(e){return e?"open":"closed"}var pZ=oq,yZ=rq,kZ=cq,_Z=dq;function fZ({...e}){return M.jsx(pZ,{"data-slot":"popover",...e})}function mZ({...e}){return M.jsx(yZ,{"data-slot":"popover-trigger",...e})}function gZ({className:e,align:t="center",sideOffset:o=4,...a}){return M.jsx(kZ,{children:M.jsx(_Z,{"data-slot":"popover-content",align:t,sideOffset:o,className:ae("bg-popover text-popover-foreground data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0 data-[state=closed]:zoom-out-95 data-[state=open]:zoom-in-95 data-[side=bottom]:slide-in-from-top-2 data-[side=left]:slide-in-from-right-2 data-[side=right]:slide-in-from-left-2 data-[side=top]:slide-in-from-bottom-2 z-50 w-72 origin-(--radix-popover-content-transform-origin) rounded-md border p-4 shadow-md outline-hidden",e),...a})})}function vZ(e){const t=new Date(e);if(isNaN(t.getTime()))return String(e);const o=String(t.getDate()).padStart(2,"0"),a=String(t.getMonth()+1).padStart(2,"0"),n=t.getFullYear();return`${o}-${a}-${n}`}function MZ(e){const t=new Date(e);if(isNaN(t.getTime()))return String(e);const o=String(t.getDate()).padStart(2,"0"),a=String(t.getMonth()+1).padStart(2,"0"),n=t.getFullYear(),i=String(t.getHours()).padStart(2,"0"),c=String(t.getMinutes()).padStart(2,"0");return`${o}-${a}-${n} ${i}:${c}`}function $Z(e){let t=e.replace(/\D/g,"");return t.startsWith("+998")&&(t=t.slice(4)),t.slice(0,9)}function wZ(e){const t=$Z(e);return t.length===0?"":[t.slice(0,2),t.slice(2,5),t.slice(5,7),t.slice(7,9)].filter(Boolean).join(" ")}const bZ=({value:e,type:t,triggerEvent:o,className:a})=>{const n=typeof e=="object"?JSON.stringify(e):String(e),i=ee.useRef(null),[c,d]=ee.useState(!1);if(ee.useEffect(()=>{const s=i.current;s&&d(s.scrollWidth>s.clientWidth)},[n]),e==null||typeof e=="number"&&isNaN(+e))return M.jsx(M.Fragment,{});const l=M.jsx("div",{ref:i,className:ae("truncate text-center max-w-[160px] md:max-w-[256px] lg:max-w-[320px] lg:text-start",a),children:xZ(n,t,o)});return c&&t!=="url"?M.jsxs(fZ,{children:[M.jsx(mZ,{className:"h-min max-w-40 md:max-w-64 lg:max-w-full lg:text-start",onClick:s=>s.stopPropagation(),title:n,children:l}),M.jsx(gZ,{onOpenAutoFocus:s=>s.preventDefault(),align:"center",className:"w-64 lg:w-80 break-words",children:n})]}):l},xZ=(e,t,o)=>{switch(t){case"text":return String(e);case"url":const[a,n]=String(e).split("|||");return M.jsx("div",{className:"text-primary underline cursor-pointer select-none",onClick:i=>{i.stopPropagation(),o&&o("onRedirect",{url:n})},children:a});case"phone":return wZ(String(e));case"date":return vZ(e);case"datetime":return MZ(e);case"currency":return Number(e).toLocaleString("uz-UZ");default:return String(e)}};oj.omit({rowSelectionAction:!0,tableData:!0,limit:!0,max_count:!0,styles:!0,onModelChange:!0});function NZ({schema:e,indexColumn:t,actionColumn:o,updateModel:a,locale:n,triggerEvent:i}){const c=[];t?.enable&&c.push({id:"index",header:"№",meta:{size:ft.xs},cell:({row:s})=>M.jsx("span",{className:t?.className,children:s.index+1})});const d=Object.entries(e).map(([s,u])=>{const{size:h=ft.md,title:k,className:p}=u,y=k?k[n]:s[0].toUpperCase()+s.slice(1);return{accessorKey:s,header:y,meta:{headerText:y,size:h},cell:m=>M.jsx(bZ,{value:m.getValue(),type:u.type||"text",triggerEvent:i,className:p})}}).filter(Boolean),l=[];return o?.enable&&o.actions.length>0&&l.push({id:"actions",header:"",meta:{size:ft.xs},cell:({row:s})=>M.jsx(nZ,{updateModel:a,type:o.type,triggerEvent:i,row:s,locale:n,actionColumn:o})}),[...c,...d,...l]}function IZ(e){try{return oj.parse(e),{success:!0}}catch(t){return console.error(t),t instanceof z.ZodError?{success:!1,error:t.issues.map(a=>a.message).join(`
67
- `)}:{success:!1,error:t}}}function LZ({className:e,...t}){return M.jsx("div",{"data-slot":"card",className:ae("bg-card text-card-foreground flex flex-col gap-6 rounded-xl border py-6 shadow-sm",e),...t})}function SZ({className:e,...t}){return M.jsx("div",{"data-slot":"card-header",className:ae("@container/card-header grid auto-rows-min grid-rows-[auto_auto] items-start gap-2 px-6 has-data-[slot=card-action]:grid-cols-[1fr_auto] [.border-b]:pb-6",e),...t})}function CZ({className:e,...t}){return M.jsx("div",{"data-slot":"card-content",className:ae("px-6",e),...t})}const zZ={info:{text:"text-blue-700",border:"border-blue-300",bg:"bg-blue-100/50",defaultIcon:"ℹ️"},warning:{text:"text-yellow-800",border:"border-yellow-300",bg:"bg-yellow-100/50",defaultIcon:"⚠️"},error:{text:"text-red-700",border:"border-red-400",bg:"bg-red-100/30",defaultIcon:"❌"},success:{text:"text-green-700",border:"border-green-300",bg:"bg-green-100/50",defaultIcon:"✅"}},AZ=({title:e,message:t,variant:o="info",icon:a,className:n=""})=>{const i=zZ[o];return M.jsxs(LZ,{className:`mx-auto max-w-md mt-8 w-full h-full flex flex-col justify-center border ${i.border} ${i.bg} ${n}`,children:[M.jsxs(SZ,{className:`flex items-center gap-2 font-semibold ${i.text}`,children:[a??i.defaultIcon,M.jsx("span",{children:e??o.charAt(0).toUpperCase()+o.slice(1)})]}),M.jsx(CZ,{className:`whitespace-normal break-words ${i.text}`,children:t})]})};function jZ(e){const{schema:t,rowSelectionAction:o,actionColumn:a,indexColumn:n,tableData:i,max_count:c=Ki,styles:d,limit:l=Ki,conditionalRowStyles:s,locale:u,updateModel:h=()=>{},triggerEvent:k=()=>{},onModelChange:p=()=>{}}=e,y=IZ(e),[_,m]=ee.useState(0),[g,w]=ee.useState(!0),[$,b]=ee.useState(i||[]),N=ee.useMemo(()=>{const D=$||[],Z=l-D.length;if(Z>0){const X=Object.fromEntries(Object.keys(t).map(K=>[K,void 0])),J=Array.from({length:Z},()=>({__empty:!0,...X}));return[...D,...J]}return D},[$,l,t]),P=ee.useCallback(()=>{const D=[],Z=[];return n?.enable&&n?.pin&&(n?.pin===Xe.left?D.push("index"):n?.pin===Xe.right&&Z.push("index")),a?.enable&&a?.pin&&a?.actions?.length>0&&(a?.pin===Xe.left?D.push("actions"):a?.pin===Xe.right&&Z.push("actions")),{left:D,right:Z}},[n,a]),C=NZ({schema:t,indexColumn:n,actionColumn:a,updateModel:h,triggerEvent:k,locale:u}),I=tD({data:N,columns:C,getCoreRowModel:Jq(),state:{columnPinning:P()},manualSorting:!0}),T=(D,Z)=>{if(!D||!g||!Z.isIntersecting||$?.length<_*l)return;const X=_+1;m(X),k("onLoadMore",{page:X,limit:l})};return ee.useEffect(()=>{_*l>=c&&w(!1)},[_,l,c]),ee.useEffect(()=>{$?.length>0&&p(D=>{D?.data?.length>0&&D.data!==$&&b(D.data||[])})},[$]),y.success?M.jsxs("main",{className:ae("max-h-[40rem] md:max-h-[48rem] lg:max-h-[56rem] flex flex-col gap-2 overflow-auto font-sans relative ",g&&"pb-2",d?.container),style:{...d?.variables},children:[M.jsxs(ED,{className:ae("w-full min-w-80 h-full table-auto border-collapse",d?.table),children:[M.jsx(ST,{styles:d?.head,table:I}),M.jsx(JD,{rowSelectionAction:o,updateModel:h,triggerEvent:k,styles:d?.body,table:I,conditionalRowStyles:s})]}),g&&M.jsx(vq,{triggerOnce:!1,as:"div",threshold:0,rootMargin:"200px 0px",onChange:(D,Z)=>T(D,Z),className:"h-10 text-muted-foreground relative flex justify-center items-center",children:M.jsx(Ii,{className:"animate-spin "})})]}):M.jsx(AZ,{message:typeof y.error=="string"?y.error:"Table configuration is invalid. Check the errors above.",variant:"error"})}Ge.ClientTable=jZ,Object.defineProperty(Ge,Symbol.toStringTag,{value:"Module"})}));
67
+ `)}:{success:!1,error:t}}}function LZ({className:e,...t}){return M.jsx("div",{"data-slot":"card",className:ae("bg-card text-card-foreground flex flex-col gap-6 rounded-xl border py-6 shadow-sm",e),...t})}function SZ({className:e,...t}){return M.jsx("div",{"data-slot":"card-header",className:ae("@container/card-header grid auto-rows-min grid-rows-[auto_auto] items-start gap-2 px-6 has-data-[slot=card-action]:grid-cols-[1fr_auto] [.border-b]:pb-6",e),...t})}function CZ({className:e,...t}){return M.jsx("div",{"data-slot":"card-content",className:ae("px-6",e),...t})}const zZ={info:{text:"text-blue-700",border:"border-blue-300",bg:"bg-blue-100/50",defaultIcon:"ℹ️"},warning:{text:"text-yellow-800",border:"border-yellow-300",bg:"bg-yellow-100/50",defaultIcon:"⚠️"},error:{text:"text-red-700",border:"border-red-400",bg:"bg-red-100/30",defaultIcon:"❌"},success:{text:"text-green-700",border:"border-green-300",bg:"bg-green-100/50",defaultIcon:"✅"}},AZ=({title:e,message:t,variant:o="info",icon:a,className:n=""})=>{const i=zZ[o];return M.jsxs(LZ,{className:`mx-auto max-w-md mt-8 w-full h-full flex flex-col justify-center border ${i.border} ${i.bg} ${n}`,children:[M.jsxs(SZ,{className:`flex items-center gap-2 font-semibold ${i.text}`,children:[a??i.defaultIcon,M.jsx("span",{children:e??o.charAt(0).toUpperCase()+o.slice(1)})]}),M.jsx(CZ,{className:`whitespace-normal break-words ${i.text}`,children:t})]})};function jZ(e){const{schema:t,rowSelectionAction:o,actionColumn:a,indexColumn:n,tableData:i,max_count:c=Ki,styles:d,limit:l=Ki,conditionalRowStyles:s,locale:u,updateModel:h=()=>{},triggerEvent:k=()=>{},onModelChange:p=()=>{}}=e,y=IZ(e),[_,m]=ee.useState(0),[g,w]=ee.useState(!0),[$,b]=ee.useState(i||[]),N=ee.useMemo(()=>{const D=$||[],Z=l-D.length;if(Z>0){const X=Object.fromEntries(Object.keys(t).map(K=>[K,void 0])),J=Array.from({length:Z},()=>({__empty:!0,...X}));return[...D,...J]}return D},[$,l,t]),P=ee.useCallback(()=>{const D=[],Z=[];return n?.enable&&n?.pin&&(n?.pin===Xe.left?D.push("index"):n?.pin===Xe.right&&Z.push("index")),a?.enable&&a?.pin&&a?.actions?.length>0&&(a?.pin===Xe.left?D.push("actions"):a?.pin===Xe.right&&Z.push("actions")),{left:D,right:Z}},[n,a]),C=NZ({schema:t,indexColumn:n,actionColumn:a,updateModel:h,triggerEvent:k,locale:u}),I=tD({data:N,columns:C,getCoreRowModel:Jq(),state:{columnPinning:P()},manualSorting:!0}),T=(D,Z)=>{if(!D||!g||!Z.isIntersecting||$?.length<_*l)return;const X=_+1;m(X),k("onLoadMore",{page:X,limit:l})};return ee.useEffect(()=>{_*l>=c&&w(!1)},[_,l,c]),ee.useEffect(()=>{$?.length>0&&p(D=>{Array.isArray(D?.data)&&D.data!==$&&b(D.data||[])})},[$]),y.success?M.jsxs("main",{className:ae("max-h-[40rem] md:max-h-[48rem] lg:max-h-[56rem] flex flex-col gap-2 overflow-auto font-sans relative ",g&&"pb-2",d?.container),style:{...d?.variables},children:[M.jsxs(ED,{className:ae("w-full min-w-80 h-full table-auto border-collapse",d?.table),children:[M.jsx(ST,{styles:d?.head,table:I}),M.jsx(JD,{rowSelectionAction:o,updateModel:h,triggerEvent:k,styles:d?.body,table:I,conditionalRowStyles:s})]}),g&&M.jsx(vq,{triggerOnce:!1,as:"div",threshold:0,rootMargin:"200px 0px",onChange:(D,Z)=>T(D,Z),className:"h-10 text-muted-foreground relative flex justify-center items-center",children:M.jsx(Ii,{className:"animate-spin "})})]}):M.jsx(AZ,{message:typeof y.error=="string"?y.error:"Table configuration is invalid. Check the errors above.",variant:"error"})}Ge.ClientTable=jZ,Object.defineProperty(Ge,Symbol.toStringTag,{value:"Module"})}));
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@teamprodevs/appsmith-custom-table",
3
- "version": "1.1.4",
3
+ "version": "1.1.5",
4
4
  "type": "module",
5
5
  "private": false,
6
6
  "keywords": [