From c839990968f45a18ba729dd0af08e276ef7ec52d Mon Sep 17 00:00:00 2001 From: igor_przybysz Date: Tue, 11 Jul 2023 09:11:15 +0200 Subject: [PATCH 1/4] Datatable - component --- demo/sites/data/datatables.html | 1200 +++++++++++ index.html | 5 + .../docs/standard/data/datatables/a-ss.html | 24 + .../docs/standard/data/datatables/a.html | 1871 +++++++++++++++++ .../standard/data/datatables/index-js.html | 765 +++++++ .../standard/data/datatables/index-ss.html | 45 + .../docs/standard/data/datatables/index.html | 1791 ++++++++++++++++ site/static/search.json | 9 + site/tailwind.config.cjs | 1 + src/js/autoinit/autoinitCallbacks.js | 12 + src/js/autoinit/index.js | 7 + src/js/data/datatables/html/columns.js | 61 + src/js/data/datatables/html/pagination.js | 84 + src/js/data/datatables/html/rows.js | 82 + src/js/data/datatables/html/table.js | 85 + src/js/data/datatables/index.js | 1154 ++++++++++ src/js/data/datatables/util.js | 62 + src/js/index.es.js | 2 + src/js/index.umd.js | 3 + src/js/plugin.cjs | 4 + 20 files changed, 7267 insertions(+) create mode 100644 demo/sites/data/datatables.html create mode 100644 site/content/docs/standard/data/datatables/a-ss.html create mode 100644 site/content/docs/standard/data/datatables/a.html create mode 100644 site/content/docs/standard/data/datatables/index-js.html create mode 100644 site/content/docs/standard/data/datatables/index-ss.html create mode 100644 site/content/docs/standard/data/datatables/index.html create mode 100644 src/js/data/datatables/html/columns.js create mode 100644 src/js/data/datatables/html/pagination.js create mode 100644 src/js/data/datatables/html/rows.js create mode 100644 src/js/data/datatables/html/table.js create mode 100644 src/js/data/datatables/index.js create mode 100644 src/js/data/datatables/util.js diff --git a/demo/sites/data/datatables.html b/demo/sites/data/datatables.html new file mode 100644 index 000000000..e4a0ee176 --- /dev/null +++ b/demo/sites/data/datatables.html @@ -0,0 +1,1200 @@ + + + + + + + + Album example · Bootstrap v5.1 + + + + + + + + + + + + + + + + +
+
+
+
+

+ Basic example - HTML markup +

+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
NamePositionOfficeAgeStart dateSalary
Tiger NixonSystem ArchitectEdinburgh612011/04/25$320,800
Garrett WintersAccountantTokyo632011/07/25$170,750
Ashton CoxJunior Technical AuthorSan Francisco662009/01/12$86,000
Cedric KellySenior Javascript DeveloperEdinburgh222012/03/29$433,060
Airi SatouAccountantTokyo332008/11/28$162,700
Brielle WilliamsonIntegration SpecialistNew York612012/12/02$372,000
Herrod ChandlerSales AssistantSan Francisco592012/08/06$137,500
Rhona DavidsonIntegration SpecialistTokyo552010/10/14$327,900
Colleen HurstJavascript DeveloperSan Francisco392009/09/15$205,500
Sonya FrostSoftware EngineerEdinburgh232008/12/13$103,600
Jena GainesOffice ManagerLondon302008/12/19$90,560
Quinn FlynnSupport LeadEdinburgh222013/03/03$342,000
Charde MarshallRegional DirectorSan Francisco362008/10/16$470,600
Haley KennedySenior Marketing DesignerLondon432012/12/18$313,500
+
+
+
+
+

+ Basic data structure +

+
+
+
+
+

+ Advanced data structure +

+
+
+
+
+

+ Search +

+ +
+
+ +
+
+ +
+
+
+

+ Advanced search +

+
+
+ + + + +
+
+ +
+
+
+

+ Selectable +

+
+
+
+
+

+ Scroll +

+
+
+
+
+

+ Fixed header +

+
+
+
+
+

+ Fixed columns +

+
+
+
+
+

+ Async data +

+ +
+
+
+
+

+ Action buttons +

+
+
+
+
+

+ Cell formatting +

+
+
+
+
+

+ Clickable rows +

+
+ + + +
+
+
+
+ + + + + + + + + + + + diff --git a/index.html b/index.html index a8554fff6..040bc248d 100644 --- a/index.html +++ b/index.html @@ -419,6 +419,11 @@

Your sites:

class="mb-1 mr-1 rounded bg-primary px-6 pb-2 pt-2.5 text-xs font-medium uppercase leading-normal text-white shadow-[0_4px_9px_-4px_#3b71ca] transition duration-150 ease-in-out hover:bg-primary-600 hover:shadow-[0_8px_9px_-4px_rgba(59,113,202,0.3),0_4px_18px_0_rgba(59,113,202,0.2)] focus:bg-primary-600 focus:shadow-[0_8px_9px_-4px_rgba(59,113,202,0.3),0_4px_18px_0_rgba(59,113,202,0.2)] focus:outline-none focus:ring-0 active:bg-primary-700 active:shadow-[0_8px_9px_-4px_rgba(59,113,202,0.3),0_4px_18px_0_rgba(59,113,202,0.2)]" >Charts advanced + Datatables
diff --git a/site/content/docs/standard/data/datatables/a-ss.html b/site/content/docs/standard/data/datatables/a-ss.html new file mode 100644 index 000000000..6b17093cf --- /dev/null +++ b/site/content/docs/standard/data/datatables/a-ss.html @@ -0,0 +1,24 @@ +--- +--- + +
  • + Import +
  • +
  • + Usage +
  • +
  • + Options +
  • +
  • + Options (column) +
  • +
  • + Classes +
  • +
  • + Methods +
  • +
  • + Events +
  • diff --git a/site/content/docs/standard/data/datatables/a.html b/site/content/docs/standard/data/datatables/a.html new file mode 100644 index 000000000..e6a1647a8 --- /dev/null +++ b/site/content/docs/standard/data/datatables/a.html @@ -0,0 +1,1871 @@ +--- +--- + + +
    + +
    + +

    + Import +

    + +

    + Importing components depends on how your application works. If you intend + to use the Tailwind Elements ES format, you must first import + the component and then initialize it with the initTE method. + If you are going to use the UMD format, just import the + tw-elements package. +

    + + + {{< twsnippet/no-demo id="api-example41" >}} + + +
    + + +
    + + +
    + +

    + Usage +

    + +

    Via data attributes

    + +

    + Using the Datatable component doesn't require any additional JavaScript + code - simply add a div wrapper with a + data-te-datatable-init attribute to your table and use other + data attributes to set all options. For ES format, you must + first import and call the initTE method. +

    + + + {{< twsnippet/no-demo id="api-example1" >}} + + + +

    Via JavaScript

    + + + {{< twsnippet/no-demo id="api-example2" >}} + + + +
    + +
    + + +
    + +

    + Options +

    + +

    + Options can be passed via data attributes or JavaScript. For data + attributes, append the option name to data-te-, as in + data-te-all-text="". +

    + +
    +
    +
    +
    + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
    + Name + + Type + + Default + Description
    + allText + + String + + "All" + + Changes text for All in the pagination select +
    + bordered + + Boolean + + false + + Adds borders to a datatable. +
    + borderless + + Boolean + + false + + Removes all borders from a datatable. +
    + clickableRows + + Boolean + + false + + Makes rows clickable. +
    + defaultValue + + String + + - + + This string will be used as a placeholder if a row doesn't + have a defined value for a column. +
    + edit + + Boolean + + false + + Enables edit mode. +
    + entries + + Number + + 10 + + Number of visible entries (pagination). +
    + entriesOptions + + Array + + [10, 25, 50, 200] + + Options available to choose from in a pagination select + (rows per page). Array with the available options may + contain numbers and 'All' to display all + entries on single page. +
    + fixedHeader + + Boolean + + false + + When it's set to true, the table's header will + remain visible while scrolling. +
    + forceSort + + Boolean + + false + + When it's set to true, the table's sort will + toggle between two options: ascending and descending. The + initial state will not be one of the options. +
    + fullPagination + + Boolean + + false + + Displays additional buttons for the first and last pages. +
    + hover + + Boolean + + false + + Changes the background color of a hovered row. +
    + loading + + Boolean + + false + + Sets the loading mode - disables interactions and displays a + loader. +
    + loadingMessage + + String + + "Loading results..." + + A message displayed while loading data. +
    + maxHeight + + Number|String + + - + + Sets a maximum height of a datatable - can be either a + string ('10%') or a number of pixels. +
    + maxWidth + + Number|String + + - + + Sets a maximum width of a datatable - can be either a string + ('10%') or a number of pixels. +
    + multi + + Boolean + + false + + Allows selecting multiple rows (selectable mode). +
    + noFoundMessage + + String + + "No matching results found" + + A message displayed when a table is empty. +
    + ofText + + String + + "of" + + A message displayed as pagination description. +
    + pagination + + Boolean + + true + + Shows/hides the pagination panel. +
    + rowsText + + String + + "Rows per page:" + + A text indicating a number of rows per page. +
    + selectable + + Boolean + + false + + Enables selecting rows with checkboxes. +
    + sm + + Boolean + + false + + Decreases a row's paddings. +
    + sortField + + String|Null + + null + + Sorts given field on init. To use it via data attributes + additionally data-te-field attribute needs to + be added to column th element. e.g. + <th data-te-field="age">Age</th> +
    + sortOrder + + String + + "asc" + + Defines an order in which initial sorting will sort. Use + 'asc' for ascending order, and 'desc' for descending order + (works only when data is injected with JS) +
    + striped + + Boolean + + false + + Slightly changes the background's color in every other row. +
    +
    +
    +
    +
    + +
    + +

    + Options (column) +

    + +
    +
    +
    +
    + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
    + Name + + Type + + Default + Description
    + field + + String + + - + + A field's name - will be used as a key for values in rows. +
    + fixed + + Boolean|String + + false + + When set to true, makes a column stick on the + left while scrolling. Changing its value to + right will do the same on the other side. For + this option to work, you need to define + width as well. +
    + format(cell, value) + + Function + + - + + Function runs for each cell, taking the DOM node & cell's + value as its parameters. +
    + label + + String + + - + + A displayed header of a column. +
    + sort + + Boolean + + true + + Enables/disables sorting for this column. +
    + width + + Number + + - + + A column's width in pixels. +
    +
    +
    +
    +
    +
    + + +
    + + +
    + +

    + Classes +

    + +

    + Custom classes can be passed via data attributes or JavaScript. For data + attributes, append the class name to + data-te-class, as in + data-te-class-border-color="". +

    + +
    +
    +
    +
    + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
    + Name + + Default + Description
    + borderColor + + border-neutral-200 dark:border-neutral-500 + + Sets border color of datatable. +
    + borderless + + border-none + + Sets border styles when + data-te-borderless="true". +
    + checkboxHeader + + relative float-left -ml-[1.5rem] mr-[6px] mt-[0.15rem] + h-[1.125rem] w-[1.125rem] appearance-none rounded-[0.25rem] + border-[0.125rem] border-solid border-neutral-300 + outline-none before:pointer-events-none before:absolute + before:h-[0.875rem] before:w-[0.875rem] before:scale-0 + before:rounded-full before:bg-transparent before:opacity-0 + before:shadow-[0px_0px_0px_13px_transparent] + before:content-[''] checked:border-primary + checked:bg-primary checked:before:opacity-[0.16] + checked:after:absolute checked:after:-mt-px + checked:after:ml-[0.25rem] checked:after:block + checked:after:h-[0.8125rem] checked:after:w-[0.375rem] + checked:after:rotate-45 checked:after:border-[0.125rem] + checked:after:border-l-0 checked:after:border-t-0 + checked:after:border-solid checked:after:border-white + checked:after:bg-transparent checked:after:content-[''] + hover:cursor-pointer hover:before:opacity-[0.04] + hover:before:shadow-[0px_0px_0px_13px_rgba(0,0,0,0.6)] + focus:shadow-none focus:transition-[border-color_0.2s] + focus:before:scale-100 focus:before:opacity-[0.12] + focus:before:shadow-[0px_0px_0px_13px_rgba(0,0,0,0.6)] + focus:before:transition-[box-shadow_0.2s,transform_0.2s] + focus:after:absolute focus:after:z-[1] focus:after:block + focus:after:h-[0.875rem] focus:after:w-[0.875rem] + focus:after:rounded-[0.125rem] focus:after:content-[''] + checked:focus:before:scale-100 + checked:focus:before:shadow-[0px_0px_0px_13px_#3b71ca] + checked:focus:before:transition-[box-shadow_0.2s,transform_0.2s] + checked:focus:after:-mt-px checked:focus:after:ml-[0.25rem] + checked:focus:after:h-[0.8125rem] + checked:focus:after:w-[0.375rem] + checked:focus:after:rotate-45 + checked:focus:after:rounded-none + checked:focus:after:border-[0.125rem] + checked:focus:after:border-l-0 + checked:focus:after:border-t-0 + checked:focus:after:border-solid + checked:focus:after:border-white + checked:focus:after:bg-transparent dark:border-neutral-600 + dark:checked:border-primary dark:checked:bg-primary + dark:focus:before:shadow-[0px_0px_0px_13px_rgba(255,255,255,0.4)] + dark:checked:focus:before:shadow-[0px_0px_0px_13px_#3b71ca] + dark:border-neutral-400 + + Sets checkbox header styles. +
    + checkboxHeaderWrapper + + mb-[0.125rem] min-h-[1.5rem] pl-[1.5rem] ml-3 flex + items-center + + Sets checkbox header wrapper styles. +
    + checkboxRow + + relative float-left -ml-[1.5rem] mr-[6px] mt-[0.15rem] + h-[1.125rem] w-[1.125rem] appearance-none rounded-[0.25rem] + border-[0.125rem] border-solid border-neutral-300 + outline-none before:pointer-events-none before:absolute + before:h-[0.875rem] before:w-[0.875rem] before:scale-0 + before:rounded-full before:bg-transparent before:opacity-0 + before:shadow-[0px_0px_0px_13px_transparent] + before:content-[''] checked:border-primary + checked:bg-primary checked:before:opacity-[0.16] + checked:after:absolute checked:after:-mt-px + checked:after:ml-[0.25rem] checked:after:block + checked:after:h-[0.8125rem] checked:after:w-[0.375rem] + checked:after:rotate-45 checked:after:border-[0.125rem] + checked:after:border-l-0 checked:after:border-t-0 + checked:after:border-solid checked:after:border-white + checked:after:bg-transparent checked:after:content-[''] + hover:cursor-pointer hover:before:opacity-[0.04] + hover:before:shadow-[0px_0px_0px_13px_rgba(0,0,0,0.6)] + focus:shadow-none focus:transition-[border-color_0.2s] + focus:before:scale-100 focus:before:opacity-[0.12] + focus:before:shadow-[0px_0px_0px_13px_rgba(0,0,0,0.6)] + focus:before:transition-[box-shadow_0.2s,transform_0.2s] + focus:after:absolute focus:after:z-[1] focus:after:block + focus:after:h-[0.875rem] focus:after:w-[0.875rem] + focus:after:rounded-[0.125rem] focus:after:content-[''] + checked:focus:before:scale-100 + checked:focus:before:shadow-[0px_0px_0px_13px_#3b71ca] + checked:focus:before:transition-[box-shadow_0.2s,transform_0.2s] + checked:focus:after:-mt-px checked:focus:after:ml-[0.25rem] + checked:focus:after:h-[0.8125rem] + checked:focus:after:w-[0.375rem] + checked:focus:after:rotate-45 + checked:focus:after:rounded-none + checked:focus:after:border-[0.125rem] + checked:focus:after:border-l-0 + checked:focus:after:border-t-0 + checked:focus:after:border-solid + checked:focus:after:border-white + checked:focus:after:bg-transparent dark:border-neutral-600 + dark:checked:border-primary dark:checked:bg-primary + dark:focus:before:shadow-[0px_0px_0px_13px_rgba(255,255,255,0.4)] + dark:checked:focus:before:shadow-[0px_0px_0px_13px_#3b71ca] + dark:border-neutral-400 + + Sets checkbox row styles. +
    + checkboxRowWrapper + + mb-[0.125rem] min-h-[1.5rem] pl-[1.5rem] ml-3 flex + items-center + + Sets checkbox row wrapper styles. +
    + color + + bg-white dark:bg-neutral-800 + + Sets background styles of datatable. +
    + column + + py-4 text-clip overflow-hidden + + Sets table columns styles. +
    + edit + + focus:outline-none + + Sets row items styles when data-te-edit="true". +
    + fixedHeader + + sticky top-0 z-30 + + Sets table header styles when + data-te-fixed-header="true. +
    + fixedHeaderBody + + sticky z-10 bg-inherit + + Sets table body styles when + data-te-fixed-header="true. +
    + hoverRow + + hover:bg-neutral-100 dark:hover:bg-neutral-700 + + Sets row hover styles when + data-te-hover="true. +
    + loadingColumn + + pointer-events-none cursor-none text-neutral-400 + dark:text-neutral-300 + + Sets column styles when + data-te-loading="true". +
    + loadingItemsWrapper + + h-[2px] relative w-full overflow-hidden + + Sets loading items wrapper styles. +
    + loadingMessage + + text-center text-neutral-500 font-ligh text-sm my-4 + dark:text-neutral-400 + + Sets loading message styles. +
    + loadingPaginationNav + + text-neutral-500 dark:text-neutral-300 + + Sets loading pagination nav styles when + data-te-loading="true". +
    + loadingPaginationRowsText + + text-neutral-500 dark:text-neutral-300 + + Sets loading pagination rows text styles when + data-te-loading="true". +
    + loadingPaginationSelectWrapper + + pointer-events-none cursor-none + + Sets loading pagination select wrapper styles when + data-te-loading="true". +
    + loadingProgressBar + + h-full w-[45%] bg-primary-400 dark:bg-primary-600 + + Sets loading progress bar styles. +
    + loadingProgressBarWrapper + + h-full animate-[progress_3s_ease-in-out_infinite] + + Sets loading progress bar wrapper styles. +
    + noFoundMessage + + pl-2 py-3 font-light text-sm dark:text-neutral-300 + + Sets no found message styles. +
    + noFoundMessageWrapper + + border-b + + Sets no found message wrapper styles. +
    + pagination + + flex md:flex-row justify-end items-center py-2 space-x-4 + text-sm flex-col + + Sets datatable pagination styles. +
    + paginationBordered + + border border-t-0 + + Sets pagination border styles when + data-te-bordered="true". +
    + paginationButtonsWrapper + + order-1 my-3 md:order-none md:my-0 md:pr-1 + + Sets pagination buttons wrapper styles. +
    + paginationEndButton + + inline-block rounded p-2.5 text-xs font-medium uppercase + leading-normal transition duration-150 ease-in-out + hover:bg-neutral-100 hover:text-primary-600 + focus:text-primary-600 focus:outline-none focus:ring-0 + active:text-primary-700 disabled:text-slate-300 + disabled:hover:bg-transparent dark:hover:bg-neutral-500 + dark:disabled:hover:bg-transparent + dark:disabled:text-neutral-600 + + Sets pagination end button styles. +
    + paginationLeftButton + + inline-block rounded p-2.5 font-medium uppercase + leading-normal transition duration-150 ease-in-out + hover:bg-neutral-100 hover:text-primary-600 + focus:text-primary-600 focus:outline-none focus:ring-0 + active:text-primary-700 disabled:text-slate-300 + disabled:hover:bg-transparent dark:hover:bg-neutral-500 + dark:disabled:hover:bg-transparent + dark:disabled:text-neutral-600 + + Sets pagination left button styles. +
    + paginationNav + + font-normal order-2 mb-3 md:order-none md:mb-0 + + Sets pagination nav styles. +
    + paginationRightButton + + inline-block rounded p-2.5 font-medium uppercase + leading-normal transition duration-150 ease-in-out + hover:bg-neutral-100 hover:text-primary-600 + focus:text-primary-600 focus:outline-none focus:ring-0 + active:text-primary-700 disabled:text-slate-300 + disabled:hover:bg-transparent dark:hover:bg-neutral-500 + dark:disabled:hover:bg-transparent + dark:disabled:text-neutral-600 + + Sets pagination right button styles. +
    + paginationRowsText + + font-light + + Sets pagination rows text styles. +
    + paginationStartButton + + inline-block rounded p-2.5 font-medium uppercase + leading-normal transition duration-150 ease-in-out + hover:bg-neutral-100 hover:text-primary-600 + focus:text-primary-600 focus:outline-none focus:ring-0 + active:text-primary-700 disabled:text-slate-300 + disabled:hover:bg-transparent dark:hover:bg-neutral-500 + dark:disabled:hover:bg-transparent + dark:disabled:text-neutral-600 + + Sets pagination start button styles. +
    + row + + border-b + + Sets row styles. +
    + rowAnimation + + transition ease-in-out duration-300 + motion-reduce:transition-none + + Sets row animation styles. +
    + rowItem + + whitespace-nowrap text-clip overflow-hidden px-6 py-4 + + Sets row item styles. +
    + scroll + + relative + + Sets scroll position styles. +
    + selectableRow + + !bg-neutral-100 dark:!bg-neutral-600 + + Sets row background styles when it is selected. +
    + selectItemsWrapper + + flex items-center space-x-4 order-3 md:order-none + + Sets select items wrapper styles. +
    + selectWrapper + + w-20 + + Sets select wrapper styles. +
    + sm + + !py-2 + + Sets rows padding styles when + data-te-sm="true". +
    + sortIcon + + w-5 h-5 pb-1 mr-1 opacity-0 text-neutral-500 + group-hover:opacity-100 transition hover:ease-in-out + transform ease-linear duration-300 + motion-reduce:transition-none dark:text-neutral-400 + + Sets sort icon styles. +
    + sortIconWrapper + + flex flex-row group + + Sets sort icon wrapper styles. +
    + striped + + [&:nth-child(odd)]:bg-neutral-50 + [&:nth-child(odd)]:dark:bg-neutral-700 + + Sets rows border styles when + data-te-striped="true". +
    + tableBordered + + border + + Sets table border styles when + data-te-bordered="true". +
    + tableHeader + + border-b font-medium + + Sets table header styles. +
    + table + + text-left text-sm font-light w-full + + Sets table styles. +
    +
    +
    +
    +
    +
    + + +
    + + +
    + +

    + Methods +

    + +
    +
    +
    +
    + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
    + Method + + Description + Example
    + dispose + + Removes the component's instance. + + myDatatable.dispose() +
    + getOrCreateInstance + + Static method which returns the datatable instance + associated to a DOM element or create a new one in case it + wasn't initialized. + + myDatatable.getOrCreateInstance() +
    + getInstance + + Static method which allows you to get the datatable instance + associated to a DOM element. + + myDatatable.getInstance() +
    + search + + Filters rows so there are only those containing the searched + phrase. + + myDatatable.search(phrase: String, column: String|Array + (optional)) +
    + setActivePage + + Sets a specific page of entries. Page count starts from + 0. + + myDatatable.setActivePage(index) +
    + update + + Updates and rerenders datatable. + + myDatatable.update(data: Object, options: Object) +
    +
    +
    +
    +
    + + + {{< twsnippet/no-demo id="api-example3" >}} + + +
    + + +
    + + +
    + +

    + Events +

    + +
    +
    +
    +
    + + + + + + + + + + + + + + + + + + + + + + + + + +
    + Event type + Description
    + render.te.datatable + + Event emitted after the component renders/updates rows. +
    + rowClick.te.datatable + + Event emitted after clicking on a row. +
    + selectRows.te.datatable + + This event fires when a user select rows with checkboxes. + You can acquire more information about selected rows with + the following properties of an emitted event: + selectedRows: Array, + selectedIndexes: Array, + allSelected: Boolean. +
    + update.te.datatable + + This event fires in an editable mode when a user updates + values. You can access the updated data inside a listener's + handler with event.rows and + event.columns fields. +
    +
    +
    +
    +
    + + + {{< twsnippet/no-demo id="api-example4" >}} + + +
    + +
    diff --git a/site/content/docs/standard/data/datatables/index-js.html b/site/content/docs/standard/data/datatables/index-js.html new file mode 100644 index 000000000..b9e1fdb95 --- /dev/null +++ b/site/content/docs/standard/data/datatables/index-js.html @@ -0,0 +1,765 @@ +--- +--- + + + diff --git a/site/content/docs/standard/data/datatables/index-ss.html b/site/content/docs/standard/data/datatables/index-ss.html new file mode 100644 index 000000000..501e90eb6 --- /dev/null +++ b/site/content/docs/standard/data/datatables/index-ss.html @@ -0,0 +1,45 @@ +--- +--- + +
  • + Basic example +
  • +
  • + Basic data structure +
  • +
  • + Advanced data structure +
  • +
  • + Search +
  • +
  • + Advanced search +
  • +
  • + Selectable +
  • +
  • + Scroll +
  • +
  • + Fixed header +
  • +
  • + Fixed columns +
  • +
  • + Async data +
  • +
  • + Action buttons +
  • +
  • + Custom cell formating +
  • +
  • + Clickable rows +
  • +
  • + Related resources +
  • diff --git a/site/content/docs/standard/data/datatables/index.html b/site/content/docs/standard/data/datatables/index.html new file mode 100644 index 000000000..3d2db639a --- /dev/null +++ b/site/content/docs/standard/data/datatables/index.html @@ -0,0 +1,1791 @@ +--- +title: "Datatables" +date: 2023-03-07T16:00:58+02:00 +draft: false +main_title: "Datatables" +subheading: "Tailwind CSS Datatables" +seo_title: "Tailwind CSS Datatables - Free Examples & Tutorial" +description: "Use responsive charts component with helper examples for simple chart, line chart, bar chart, radar chart, pie chart, doughnut & more. Open source license." +image: "https://tecdn.b-cdn.net/img/docs/data/table.webp" +video: "https://www.youtube.com/watch?v=-GmnyjgI4Jc&ab_channel=Keepcoding" +url: "docs/standard/data/datatables/" +menu: + data: + name: "Datatables" +autoinits: "Datatable" +--- + + +
    + +

    + Basic example - HTML markup +

    + + +

    + The Datatable component can render your data in three ways. In the first + one, you simply create a HTML markup for your table nested within a div tag + with a data-te-datatable-init attribute - you can customize + your table later by adding data-te-attributes to the wrapper. + Some of the more advanced options for columns, described in the + Advanced Data Structure + section can be also used by setting data-te-attributes directly + to a th tag (f.e. + <th data-te-sort="false">). +

    + + + + {{< twsnippet/demo id="example1">}} +
    + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
    NamePositionOfficeAgeStart dateSalary
    Tiger NixonSystem ArchitectEdinburgh612011/04/25$320,800
    Garrett WintersAccountantTokyo632011/07/25$170,750
    Ashton CoxJunior Technical AuthorSan Francisco662009/01/12$86,000
    Cedric KellySenior Javascript DeveloperEdinburgh222012/03/29$433,060
    Airi SatouAccountantTokyo332008/11/28$162,700
    Brielle WilliamsonIntegration SpecialistNew York612012/12/02$372,000
    Herrod ChandlerSales AssistantSan Francisco592012/08/06$137,500
    Rhona DavidsonIntegration SpecialistTokyo552010/10/14$327,900
    Colleen HurstJavascript DeveloperSan Francisco392009/09/15$205,500
    Sonya FrostSoftware EngineerEdinburgh232008/12/13$103,600
    Jena GainesOffice ManagerLondon302008/12/19$90,560
    Quinn FlynnSupport LeadEdinburgh222013/03/03$342,000
    Charde MarshallRegional DirectorSan Francisco362008/10/16$470,600
    Haley KennedySenior Marketing DesignerLondon432012/12/18$313,500
    +
    + {{< /twsnippet/demo >}} + + + +
    + + + +
    + +

    + Basic data structure +

    + + +

    + The second option is a very basic data structure, where columns are + represented by an array of strings and so is each row. The table will match + each string in a row to a corresponding index in a columns array. This data + structure, as it's based on indexes, not key-value pairs, can be easily used + for displaying data from the CSV format. +

    + + + + {{< twsnippet/demo id="example2">}} +
    + {{< /twsnippet/demo >}} + + + +
    + + + +
    + +

    + Advanced data structure +

    + + +

    + The last and most advanced data structure allows customizing each column + (sort, width, fixed, field) and matches values from each row to a column in + which the `field` equals to a given key value. This data format can be + easily used to display JSON data. +

    + + + + + {{< twsnippet/demo id="example3">}} +
    + {{< /twsnippet/demo >}} + + + +
    + + + +
    + + + + +

    + The search field is not a part of the Datatable - place an input field on + your page and use .search() method to filter entries. +

    + + + + {{< twsnippet/demo id="example4">}} +
    +
    + +
    +
    + + {{< /twsnippet/demo >}} + + + +
    + + + +
    + + + + +

    + When using the searching method, you can specify which columns it should + take under consideration - pass as a second argument a field (or array of + fields). By default, searching will apply to all columns. +

    + + + + {{< twsnippet/demo id="example5">}} +
    +
    + + + + +
    +
    + + {{< /twsnippet/demo >}} + + + +
    + + + +
    + +

    + Selectable rows +

    + + +

    + When the data-te-selectable option is set to true, + user can interact with your table by selecting rows - you can get the + selected rows by listening to the + selectRows.te.datatable event. +

    + + + + {{< twsnippet/demo id="example6">}} +
    + {{< /twsnippet/demo >}} + + + +
    + + + +
    + +

    + Scroll +

    + + +

    + Setting maximum height/width will enable vertical/horizontal scrolling. +

    + + + + {{< twsnippet/demo id="example7">}} +
    + {{< /twsnippet/demo >}} + + + +
    + + + +
    + +

    + Fixed header +

    + + +

    + Use the data-te-fixed-header attribute to ensure that a table's + header is always visible while scrolling. +

    + + + + {{< twsnippet/demo id="example8">}} +
    + {{< /twsnippet/demo >}} + + + +
    + + + +
    + +

    + Fixed columns +

    + + +

    + Making a column sticky requires setting two options - width and fixed. A + first option is a number of pixels, while the other one can be either a + true ( in which case the column will stick on the left) or a + string right. +

    + + + + + + {{< twsnippet/demo id="example9">}} +
    + {{< /twsnippet/demo >}} + + + +
    + + + +
    + +

    + Async data +

    + + +

    + Loading content asynchronously is an important part of working with data + tables - with TE Datatable you can easily display content after fetching it + from API by using the update method. Additionally, setting a + loading option to true will disable all + interactions and display a simple loader while awaiting data. +

    +

    + The example below demonstrates loading data after the button is pressed. +

    + + + + + {{< twsnippet/demo id="example10">}} +
    + {{< /twsnippet/demo >}} + + + +
    + + + +
    + +

    + Action buttons +

    + + +

    + With the Datatable it's possible to render custom content, such as action + buttons and attach listeners to their events. Keep in mind, that the + component rerenders content when various actions occur (f.e. sort, search) + and event listeners need to be updated. To make it possible, the components + emits a custom event render.te.datatable. +

    + + + + {{< twsnippet/demo id="example11">}} +
    + {{< /twsnippet/demo >}} + + + +
    + + + +
    + +

    + Cell formating +

    + + +

    Use cell formatting to color individual cells.

    + + + + {{< twsnippet/demo id="example12">}} +
    + {{< /twsnippet/demo >}} + + + +
    + + + +
    + +

    + Clickable rows +

    + + +

    Click on the row to preview the message.

    + + + + + + {{< twsnippet/demo id="example13">}} +
    + + + + {{< /twsnippet/demo >}} + + + +
    + + +
    + + + + + +

    + If you are looking for more advanced options, try + Bootstrap Datatables + from MDBootstrap. +

    diff --git a/site/static/search.json b/site/static/search.json index 5df9d2f14..9fa9b1919 100644 --- a/site/static/search.json +++ b/site/static/search.json @@ -769,6 +769,15 @@ "table": 1 } }, + { + "href": "/docs/standard/data/datatables/", + "name": "Datatables", + "keywords": ["datatables"], + "category": "Data", + "priority": { + "table": 1 + } + }, { "href": "/docs/standard/methods/ripple/", "name": "Ripple", diff --git a/site/tailwind.config.cjs b/site/tailwind.config.cjs index c4e871fb5..31acccb3d 100644 --- a/site/tailwind.config.cjs +++ b/site/tailwind.config.cjs @@ -58,5 +58,6 @@ module.exports = { "animate-[zoom-out_1s_ease-in-out]", "animate-[tada_1s_ease-in-out]", "animate-[spinner-grow_1s_ease-in-out]", + "animate-[progress_3s_ease-in-out_infinite]", ], }; diff --git a/src/js/autoinit/autoinitCallbacks.js b/src/js/autoinit/autoinitCallbacks.js index cb224b95f..0c478d5d6 100644 --- a/src/js/autoinit/autoinitCallbacks.js +++ b/src/js/autoinit/autoinitCallbacks.js @@ -181,6 +181,17 @@ const popoverCallback = (component, initSelector) => { }); }; +const datatableCallback = (component, initSelector) => { + SelectorEngine.find(initSelector).forEach((datatable) => { + let instance = component.getInstance(datatable); + if (!instance) { + instance = new component(datatable); + } + + return instance; + }); +}; + export { dropdownCallback, tabCallback, @@ -191,4 +202,5 @@ export { collapseCallback, tooltipsCallback, popoverCallback, + datatableCallback, }; diff --git a/src/js/autoinit/index.js b/src/js/autoinit/index.js index 2a0f3ae23..524055935 100644 --- a/src/js/autoinit/index.js +++ b/src/js/autoinit/index.js @@ -10,6 +10,7 @@ import { collapseCallback, tooltipsCallback, popoverCallback, + datatableCallback, } from "./autoinitCallbacks"; import { chartsCallback } from "./chartsInit"; @@ -97,6 +98,12 @@ const defaultInitSelectors = { isToggler: false, callback: tooltipsCallback, }, + datatable: { + name: "Datatable", + selector: "[data-te-datatable-init]", + isToggler: false, + callback: datatableCallback, + }, // advancedInits chart: { diff --git a/src/js/data/datatables/html/columns.js b/src/js/data/datatables/html/columns.js new file mode 100644 index 000000000..2383fffe0 --- /dev/null +++ b/src/js/data/datatables/html/columns.js @@ -0,0 +1,61 @@ +/* eslint-disable indent */ + +const columns = ( + columns, + selectable, + multi, + bordered, + sm, + loading, + classes +) => { + const SELECTOR_SORT_ICON = "data-te-datatable-sort-icon-ref"; + const SELECTOR_HEADER_CHECKBOX = "data-te-datatable-header-checkbox-ref"; + const checkboxHeader = multi + ? ` + +
    + +
    + + ` + : ''; + const headers = columns.map((column, i) => { + const fixedOffset = column.fixed + ? columns + .filter((cell, j) => cell.fixed === column.fixed && j < i) + .reduce((a, b) => a + b.width, 0) + : null; + return `${ + column.sort + ? `
    + + ` + : "" + } ${ + column.label + }
    `; + }); + + return [selectable ? checkboxHeader : "", ...headers].join("\n"); +}; + +export default columns; diff --git a/src/js/data/datatables/html/pagination.js b/src/js/data/datatables/html/pagination.js new file mode 100644 index 000000000..c4cb72de8 --- /dev/null +++ b/src/js/data/datatables/html/pagination.js @@ -0,0 +1,84 @@ +/* eslint-disable indent */ +const pagination = ( + { text, entries, entriesOptions, fullPagination, rowsText, allText, classes }, + loading, + bordered +) => { + const SELECTOR_SELECT = "data-te-datatable-select-ref"; + const SELECTOR_PAGINATION_NAV = "data-te-datatable-pagination-nav-ref"; + const SELECTOR_PAGINATION_RIGHT = "data-te-datatable-pagination-right-ref"; + const SELECTOR_PAGINATION_LEFT = "data-te-datatable-pagination-left-ref"; + const SELECTOR_PAGINATION_START = "data-te-datatable-pagination-start-ref"; + const SELECTOR_PAGINATION_END = "data-te-datatable-pagination-end-ref"; + const options = entriesOptions + .map((option) => { + if (option === "All") { + return ``; + } + return ``; + }) + .join("\n"); + + return ` +
    +
    +

    ${rowsText}

    +
    + +
    +
    +
    + ${text} +
    +
    + ${ + fullPagination + ? `` + : "" + } + + + ${ + fullPagination + ? `` + : "" + } +
    +
    +`; +}; + +export default pagination; diff --git a/src/js/data/datatables/html/rows.js b/src/js/data/datatables/html/rows.js new file mode 100644 index 000000000..15eb35a37 --- /dev/null +++ b/src/js/data/datatables/html/rows.js @@ -0,0 +1,82 @@ +/* eslint-disable indent */ +const rows = ({ + rows, + columns, + noFoundMessage, + edit, + selectable, + loading, + bordered, + borderless, + striped, + hover, + sm, + classes, +}) => { + const rowsTemplate = rows.map((row) => { + const SELECTOR_ROW = "data-te-datatable-row-ref"; + const SELECTOR_ROW_CHECKBOX = "data-te-datatable-row-checkbox-ref"; + const SELECTOR_CELL = "data-te-datatable-cell-ref"; + const checkbox = ` + +
    + +
    + `; + const innerRow = columns + .map((column, i) => { + const style = {}; + + if (column.width) { + style["min-width"] = `${column.width - 1}px`; + style["max-width"] = `${column.width}px`; + style.width = `${column.width}px`; + } + if (column.fixed) { + const fixedOffset = columns + .filter((cell, j) => cell.fixed === column.fixed && j < i) + .reduce((a, b) => a + b.width, 0); + + style[ + column.fixed === "right" ? "right" : "left" + ] = `${fixedOffset}px`; + } + + const cssText = Object.keys(style) + .map((property) => `${property}: ${style[property]}`) + .join("; "); + + return `${row[column.field]}`; + }) + .join(""); + + return `${selectable ? checkbox : ""}${innerRow}`; + }); + + return rows.length > 0 || loading + ? rowsTemplate.join("\n") + : `${noFoundMessage}`; +}; + +export default rows; diff --git a/src/js/data/datatables/html/table.js b/src/js/data/datatables/html/table.js new file mode 100644 index 000000000..16e7abc60 --- /dev/null +++ b/src/js/data/datatables/html/table.js @@ -0,0 +1,85 @@ +/* eslint-disable indent */ +import paginationTemplate from "./pagination"; +import generateColumns from "./columns"; +import generateRows from "./rows"; + +const tableTemplate = ({ + columns, + rows, + noFoundMessage, + edit, + multi, + selectable, + loading, + loadingMessage, + pagination, + bordered, + borderless, + striped, + hover, + fixedHeader, + sm, + classes, +}) => { + const SELECTOR_BODY = "data-te-datatable-inner-ref"; + const SELECTOR_HEADER = "data-te-datatable-header-ref"; + const rowsTemplate = generateRows({ + rows, + columns, + noFoundMessage, + edit, + loading, + selectable, + bordered, + borderless, + striped, + hover, + sm, + classes, + }); + const columnsTemplate = generateColumns( + columns, + selectable, + multi, + bordered, + sm, + loading, + classes + ); + + const table = ` +
    + + + + ${columnsTemplate} + + + + ${loading ? "" : rowsTemplate} + +
    +
    +${ + loading + ? ` +
    +
    +
    +
    +
    +

    ${loadingMessage}

    +` + : "" +} +${pagination.enable ? paginationTemplate(pagination, loading, bordered) : ""} + `; + + return { table, rows: rowsTemplate, column: columnsTemplate }; +}; + +export default tableTemplate; diff --git a/src/js/data/datatables/index.js b/src/js/data/datatables/index.js new file mode 100644 index 000000000..6118a1b26 --- /dev/null +++ b/src/js/data/datatables/index.js @@ -0,0 +1,1154 @@ +import PerfectScrollbar from "../../methods/perfect-scrollbar"; +import { typeCheckConfig } from "../../util/index"; +import Data from "../../dom/data"; +import EventHandler from "../../dom/event-handler"; +import Manipulator from "../../dom/manipulator"; +import SelectorEngine from "../../dom/selector-engine"; +import tableTemplate from "./html/table"; //eslint-disable-line +import { search, sort, paginate } from "./util"; +import Select from "../../forms/select"; + +/** + * ------------------------------------------------------------------------ + * Constants + * ------------------------------------------------------------------------ + */ + +const NAME = "datatable"; +const ATTR_NAME = `data-te-${NAME}`; +const DATA_KEY = `te.${NAME}`; +const EVENT_KEY = `.${DATA_KEY}`; + +const SELECTOR_BODY = `[${ATTR_NAME}-inner-ref]`; +const SELECTOR_CELL = `[${ATTR_NAME}-cell-ref]`; +const SELECTOR_HEADER = `[${ATTR_NAME}-header-ref]`; +const SELECTOR_HEADER_CHECKBOX = `[${ATTR_NAME}-header-checkbox-ref]`; +const SELECTOR_PAGINATION_RIGHT = `[${ATTR_NAME}-pagination-right-ref]`; +const SELECTOR_PAGINATION_LEFT = `[${ATTR_NAME}-pagination-left-ref]`; +const SELECTOR_PAGINATION_START = `[${ATTR_NAME}-pagination-start-ref]`; +const SELECTOR_PAGINATION_END = `[${ATTR_NAME}-pagination-end-ref]`; +const SELECTOR_PAGINATION_NAV = `[${ATTR_NAME}-pagination-nav-ref]`; +const SELECTOR_SELECT = `[${ATTR_NAME}-select-ref]`; +const SELECTOR_SORT_ICON = `[${ATTR_NAME}-sort-icon-ref]`; +const SELECTOR_ROW = `[${ATTR_NAME}-row-ref]`; +const SELECTOR_ROW_CHECKBOX = `[${ATTR_NAME}-row-checkbox-ref]`; + +const EVENT_SELECT = `selectRows${EVENT_KEY}`; +const EVENT_RENDER = `render${EVENT_KEY}`; +const EVENT_ROW_CLICK = `rowClick${EVENT_KEY}`; +const EVENT_UPDATE = `update${EVENT_KEY}`; + +const BORDER_COLOR_CLASSES = "border-neutral-200 dark:border-neutral-500"; +const BORDERLESS_CLASSES = "border-none"; +const CHECKBOX_HEADER_CLASSES = + "relative float-left -ml-[1.5rem] mr-[6px] mt-[0.15rem] h-[1.125rem] w-[1.125rem] appearance-none rounded-[0.25rem] border-[0.125rem] border-solid border-neutral-300 outline-none before:pointer-events-none before:absolute before:h-[0.875rem] before:w-[0.875rem] before:scale-0 before:rounded-full before:bg-transparent before:opacity-0 before:shadow-[0px_0px_0px_13px_transparent] before:content-[''] checked:border-primary checked:bg-primary checked:before:opacity-[0.16] checked:after:absolute checked:after:-mt-px checked:after:ml-[0.25rem] checked:after:block checked:after:h-[0.8125rem] checked:after:w-[0.375rem] checked:after:rotate-45 checked:after:border-[0.125rem] checked:after:border-l-0 checked:after:border-t-0 checked:after:border-solid checked:after:border-white checked:after:bg-transparent checked:after:content-[''] hover:cursor-pointer hover:before:opacity-[0.04] hover:before:shadow-[0px_0px_0px_13px_rgba(0,0,0,0.6)] focus:shadow-none focus:transition-[border-color_0.2s] focus:before:scale-100 focus:before:opacity-[0.12] focus:before:shadow-[0px_0px_0px_13px_rgba(0,0,0,0.6)] focus:before:transition-[box-shadow_0.2s,transform_0.2s] focus:after:absolute focus:after:z-[1] focus:after:block focus:after:h-[0.875rem] focus:after:w-[0.875rem] focus:after:rounded-[0.125rem] focus:after:content-[''] checked:focus:before:scale-100 checked:focus:before:shadow-[0px_0px_0px_13px_#3b71ca] checked:focus:before:transition-[box-shadow_0.2s,transform_0.2s] checked:focus:after:-mt-px checked:focus:after:ml-[0.25rem] checked:focus:after:h-[0.8125rem] checked:focus:after:w-[0.375rem] checked:focus:after:rotate-45 checked:focus:after:rounded-none checked:focus:after:border-[0.125rem] checked:focus:after:border-l-0 checked:focus:after:border-t-0 checked:focus:after:border-solid checked:focus:after:border-white checked:focus:after:bg-transparent dark:border-neutral-600 dark:checked:border-primary dark:checked:bg-primary dark:focus:before:shadow-[0px_0px_0px_13px_rgba(255,255,255,0.4)] dark:checked:focus:before:shadow-[0px_0px_0px_13px_#3b71ca] dark:border-neutral-400"; +const CHECKBOX_HEADER_WRAPPER_CLASSES = + "mb-[0.125rem] min-h-[1.5rem] pl-[1.5rem] ml-3 flex items-center"; +const CHECKBOX_ROW_CLASSES = + "relative float-left -ml-[1.5rem] mr-[6px] mt-[0.15rem] h-[1.125rem] w-[1.125rem] appearance-none rounded-[0.25rem] border-[0.125rem] border-solid border-neutral-300 outline-none before:pointer-events-none before:absolute before:h-[0.875rem] before:w-[0.875rem] before:scale-0 before:rounded-full before:bg-transparent before:opacity-0 before:shadow-[0px_0px_0px_13px_transparent] before:content-[''] checked:border-primary checked:bg-primary checked:before:opacity-[0.16] checked:after:absolute checked:after:-mt-px checked:after:ml-[0.25rem] checked:after:block checked:after:h-[0.8125rem] checked:after:w-[0.375rem] checked:after:rotate-45 checked:after:border-[0.125rem] checked:after:border-l-0 checked:after:border-t-0 checked:after:border-solid checked:after:border-white checked:after:bg-transparent checked:after:content-[''] hover:cursor-pointer hover:before:opacity-[0.04] hover:before:shadow-[0px_0px_0px_13px_rgba(0,0,0,0.6)] focus:shadow-none focus:transition-[border-color_0.2s] focus:before:scale-100 focus:before:opacity-[0.12] focus:before:shadow-[0px_0px_0px_13px_rgba(0,0,0,0.6)] focus:before:transition-[box-shadow_0.2s,transform_0.2s] focus:after:absolute focus:after:z-[1] focus:after:block focus:after:h-[0.875rem] focus:after:w-[0.875rem] focus:after:rounded-[0.125rem] focus:after:content-[''] checked:focus:before:scale-100 checked:focus:before:shadow-[0px_0px_0px_13px_#3b71ca] checked:focus:before:transition-[box-shadow_0.2s,transform_0.2s] checked:focus:after:-mt-px checked:focus:after:ml-[0.25rem] checked:focus:after:h-[0.8125rem] checked:focus:after:w-[0.375rem] checked:focus:after:rotate-45 checked:focus:after:rounded-none checked:focus:after:border-[0.125rem] checked:focus:after:border-l-0 checked:focus:after:border-t-0 checked:focus:after:border-solid checked:focus:after:border-white checked:focus:after:bg-transparent dark:border-neutral-600 dark:checked:border-primary dark:checked:bg-primary dark:focus:before:shadow-[0px_0px_0px_13px_rgba(255,255,255,0.4)] dark:checked:focus:before:shadow-[0px_0px_0px_13px_#3b71ca] dark:border-neutral-400"; +const CHECKBOX_ROW_WRAPPER_CLASSES = + "mb-[0.125rem] min-h-[1.5rem] pl-[1.5rem] ml-3 flex items-center"; +const COLOR_CLASSES = "bg-white dark:bg-neutral-800"; +const COLUMNS_CLASSES = "py-4 text-clip overflow-hidden"; +const EDIT_CLASSES = "focus:outline-none"; +const FIXED_HEADER_CLASSES = "sticky top-0 z-30"; +const FIXED_HEADER_BODY_CLASSES = "sticky z-10 bg-inherit"; +const HOVER_ROW_CLASSES = "hover:bg-neutral-100 dark:hover:bg-neutral-700"; +const LOADING_COLUMN_CLASSES = + "pointer-events-none cursor-none text-neutral-400 dark:text-neutral-300"; +const LOADING_ITEMS_WRAPPER_CLASSES = "h-[2px] relative w-full overflow-hidden"; +const LOADING_MESSAGE_CLASSES = + "text-center text-neutral-500 font-ligh text-sm my-4 dark:text-neutral-400"; +const LOADING_PAGINATION_NAV_CLASSES = "text-neutral-500 dark:text-neutral-300"; +const LOADING_PAGINATION_ROWS_TEXT_CLASSES = + "text-neutral-500 dark:text-neutral-300"; +const LOADING_PAGINATION_SELECT_WRAPPER_CLASSES = + "pointer-events-none cursor-none"; +const LOADING_PROGRESS_BAR_CLASSES = + "h-full w-[45%] bg-primary-400 dark:bg-primary-600"; +const LOADING_PROGRESS_BAR_WRAPPER_CLASSES = + "h-full animate-[progress_3s_ease-in-out_infinite]"; +const NO_FOUND_MESSAGE_CLASSES = + "pl-2 py-3 font-light text-sm dark:text-neutral-300"; +const NO_FOUND_MESSAGE_WRAPPER_CLASSES = "border-b"; +const PAGINATION_CLASSES = + "flex md:flex-row justify-end items-center py-2 space-x-4 text-sm flex-col"; +const PAGINATION_BORDERED_CLASSES = "border border-t-0"; +const PAGINATION_BUTTONS_WRAPPER_CLASSES = + "order-1 my-3 md:order-none md:my-0 md:pr-1"; +const PAGINATION_END_BUTTON_CLASSES = + "inline-block rounded p-2.5 text-xs font-medium uppercase leading-normal transition duration-150 ease-in-out hover:bg-neutral-100 hover:text-primary-600 focus:text-primary-600 focus:outline-none focus:ring-0 active:text-primary-700 disabled:text-slate-300 disabled:hover:bg-transparent dark:hover:bg-neutral-500 dark:disabled:hover:bg-transparent dark:disabled:text-neutral-600"; +const PAGINATION_LEFT_BUTTON_CLASSES = + "inline-block rounded p-2.5 font-medium uppercase leading-normal transition duration-150 ease-in-out hover:bg-neutral-100 hover:text-primary-600 focus:text-primary-600 focus:outline-none focus:ring-0 active:text-primary-700 disabled:text-slate-300 disabled:hover:bg-transparent dark:hover:bg-neutral-500 dark:disabled:hover:bg-transparent dark:disabled:text-neutral-600"; +const PAGINATION_NAV_CLASSES = "font-normal order-2 mb-3 md:order-none md:mb-0"; +const PAGINATION_RIGHT_BUTTON_CLASSES = + "inline-block rounded p-2.5 font-medium uppercase leading-normal transition duration-150 ease-in-out hover:bg-neutral-100 hover:text-primary-600 focus:text-primary-600 focus:outline-none focus:ring-0 active:text-primary-700 disabled:text-slate-300 disabled:hover:bg-transparent dark:hover:bg-neutral-500 dark:disabled:hover:bg-transparent dark:disabled:text-neutral-600"; +const PAGINATION_ROWS_TEXT_CLASSES = "font-light"; +const PAGINATION_START_BUTTON_CLASSES = + "inline-block rounded p-2.5 font-medium uppercase leading-normal transition duration-150 ease-in-out hover:bg-neutral-100 hover:text-primary-600 focus:text-primary-600 focus:outline-none focus:ring-0 active:text-primary-700 disabled:text-slate-300 disabled:hover:bg-transparent dark:hover:bg-neutral-500 dark:disabled:hover:bg-transparent dark:disabled:text-neutral-600"; +const ROW_CLASSES = "border-b"; +const ROW_ANIMATION_CLASSES = + "transition ease-in-out duration-300 motion-reduce:transition-none"; +const ROW_ITEM_CLASSES = + "whitespace-nowrap text-clip overflow-hidden px-6 py-4"; +const SCROLL_CLASSES = "relative"; +const SELECTABLE_ROW_CLASSES = "!bg-neutral-100 dark:!bg-neutral-600"; +const SELECT_ITEMS_WRAPPER_CLASSES = + "flex items-center space-x-4 order-3 md:order-none"; +const SELECT_WRAPPER_CLASSES = "w-20"; +const SM_CLASSES = "!py-2"; +const SORT_ICON_CLASSES = + "w-5 h-5 pb-1 mr-1 opacity-0 text-neutral-500 group-hover:opacity-100 transition hover:ease-in-out transform ease-linear duration-300 motion-reduce:transition-none dark:text-neutral-400"; +const SORT_ICON_WRAPPER_CLASSES = "flex flex-row group"; +const STRIPED_CLASSES = + "[&:nth-child(odd)]:bg-neutral-50 [&:nth-child(odd)]:dark:bg-neutral-700"; +const TABLE_BORDERED_CLASSES = "border"; +const TABLE_HEADER_CLASSES = "border-b font-medium"; +const TABLE_CLASSES = "text-left text-sm font-light w-full"; + +const TYPE_OPTIONS = { + bordered: "boolean", + borderless: "boolean", + clickableRows: "boolean", + defaultValue: "string", + edit: "boolean", + entries: "(number|string)", + entriesOptions: "array", + fullPagination: "boolean", + hover: "boolean", + loading: "boolean", + loadingMessage: "string", + maxWidth: "(null|number|string)", + maxHeight: "(null|number|string)", + multi: "boolean", + noFoundMessage: "string", + pagination: "boolean", + selectable: "boolean", + sm: "boolean", + sortField: "(null|string)", + sortOrder: "string", + fixedHeader: "boolean", + striped: "boolean", + rowsText: "string", + ofText: "string", + allText: "string", + forceSort: "boolean", +}; + +const DEFAULT_OPTIONS = { + bordered: false, + borderless: false, + clickableRows: false, + defaultValue: "-", + edit: false, + entries: 10, + entriesOptions: [10, 25, 50, 200], + fixedHeader: false, + fullPagination: false, + hover: false, + loading: false, + loadingMessage: "Loading results...", + maxWidth: null, + maxHeight: null, + multi: false, + noFoundMessage: "No matching results found", + pagination: true, + selectable: false, + sm: false, + sortField: null, + sortOrder: "asc", + striped: false, + rowsText: "Rows per page:", + ofText: "of", + allText: "All", + forceSort: false, +}; + +const TYPE_COLUMN_FIELDS = { + label: "string", + field: "string", + fixed: "(boolean|string)", + format: "(function|null)", + width: "(number|null)", + sort: "boolean", + columnIndex: "number", +}; + +const DEFAULT_COLUMN = { + label: "", + field: "", + fixed: false, + format: null, + width: null, + sort: true, + columnIndex: 0, +}; + +const DefaultClasses = { + table: TABLE_CLASSES, + tableHeader: TABLE_HEADER_CLASSES, + column: COLUMNS_CLASSES, + pagination: PAGINATION_CLASSES, + selectWrapper: SELECT_WRAPPER_CLASSES, + scroll: SCROLL_CLASSES, + tableBordered: TABLE_BORDERED_CLASSES, + paginationBordered: PAGINATION_BORDERED_CLASSES, + borderless: BORDERLESS_CLASSES, + checkboxRowWrapper: CHECKBOX_ROW_WRAPPER_CLASSES, + checkboxRow: CHECKBOX_ROW_CLASSES, + checkboxHeaderWrapper: CHECKBOX_HEADER_WRAPPER_CLASSES, + checkboxHeader: CHECKBOX_HEADER_CLASSES, + row: ROW_CLASSES, + rowItem: ROW_ITEM_CLASSES, + striped: STRIPED_CLASSES, + sortIconWrapper: SORT_ICON_WRAPPER_CLASSES, + sortIcon: SORT_ICON_CLASSES, + paginationRowsText: PAGINATION_ROWS_TEXT_CLASSES, + paginationNav: PAGINATION_NAV_CLASSES, + paginationButtonsWrapper: PAGINATION_BUTTONS_WRAPPER_CLASSES, + hoverRow: HOVER_ROW_CLASSES, + borderColor: BORDER_COLOR_CLASSES, + color: COLOR_CLASSES, + fixedHeader: FIXED_HEADER_CLASSES, + fixedHeaderBody: FIXED_HEADER_BODY_CLASSES, + selectableRow: SELECTABLE_ROW_CLASSES, + rowAnimation: ROW_ANIMATION_CLASSES, + sm: SM_CLASSES, + edit: EDIT_CLASSES, + selectItemsWrapper: SELECT_ITEMS_WRAPPER_CLASSES, + paginationStartButton: PAGINATION_START_BUTTON_CLASSES, + paginationLeftButton: PAGINATION_LEFT_BUTTON_CLASSES, + paginationRightButton: PAGINATION_RIGHT_BUTTON_CLASSES, + paginationEndButton: PAGINATION_END_BUTTON_CLASSES, + loadingItemsWrapper: LOADING_ITEMS_WRAPPER_CLASSES, + loadingProgressBarWrapper: LOADING_PROGRESS_BAR_WRAPPER_CLASSES, + loadingProgressBar: LOADING_PROGRESS_BAR_CLASSES, + loadingMessage: LOADING_MESSAGE_CLASSES, + loadingPaginationRowsText: LOADING_PAGINATION_ROWS_TEXT_CLASSES, + loadingPaginationSelectWrapper: LOADING_PAGINATION_SELECT_WRAPPER_CLASSES, + loadingPaginationNav: LOADING_PAGINATION_NAV_CLASSES, + loadingColumn: LOADING_COLUMN_CLASSES, + noFoundMessageWrapper: NO_FOUND_MESSAGE_WRAPPER_CLASSES, + noFoundMessage: NO_FOUND_MESSAGE_CLASSES, +}; + +const DefaultClassesType = { + table: "string", + tableHeader: "string", + column: "string", + pagination: "string", + selectWrapper: "string", + scroll: "string", + tableBordered: "string", + paginationBordered: "string", + borderless: "string", + checkboxRowWrapper: "string", + checkboxRow: "string", + checkboxHeaderWrapper: "string", + checkboxHeader: "string", + row: "string", + rowItem: "string", + striped: "string", + sortIconWrapper: "string", + sortIcon: "string", + paginationRowsText: "string", + paginationNav: "string", + paginationButtonsWrapper: "string", + hoverRow: "string", + borderColor: "string", + color: "string", + fixedHeader: "string", + fixedHeaderBody: "string", + selectableRow: "string", + rowAnimation: "string", + sm: "string", + edit: "string", + selectItemsWrapper: "string", + paginationStartButton: "string", + paginationLeftButton: "string", + paginationRightButton: "string", + paginationEndButton: "string", + loadingItemsWrapper: "string", + loadingProgressBarWrapper: "string", + loadingProgressBar: "string", + loadingMessage: "string", + loadingPaginationRowsText: "string", + loadingPaginationSelectWrapper: "string", + loadingPaginationNav: "string", + loadingColumn: "string", + noFoundMessageWrapper: "string", + noFoundMessage: "string", +}; +/** + * ------------------------------------------------------------------------ + * Class Definition + * ------------------------------------------------------------------------ + */ + +class Datatable { + constructor(element, data = {}, options = {}, classes = {}) { + this._element = element; + + this._options = this._getOptions(options); + this._classes = this._getClasses(classes); + + this._sortReverse = false; + this._activePage = 0; + + this._search = ""; + this._searchColumn = null; + + this._paginationLeft = null; + this._paginationRight = null; + this._paginationStart = null; + this._paginationEnd = null; + this._select = null; + this._selectInstance = null; + + this._selected = []; + this._checkboxes = null; + this._headerCheckbox = null; + this._rows = this._getRows(data.rows); + this._columns = this._getColumns(data.columns); + + if (this._element) { + Data.setData(element, DATA_KEY, this); + + this._perfectScrollbar = null; + this._setup(); + } + } + + // Getters + + static get NAME() { + return NAME; + } + + get columns() { + return this._columns.map((column, index) => { + let template = { + ...DEFAULT_COLUMN, + field: `field_${index}`, + columnIndex: index, + }; + + if (typeof column === "string") { + template.label = column; + } else if (typeof column === "object") { + template = { + ...template, + ...column, + }; + } + + typeCheckConfig("column", template, TYPE_COLUMN_FIELDS); + + return template; + }); + } + + get rows() { + return this._rows.map((row, index) => { + const output = { + rowIndex: index, + }; + + if (Array.isArray(row)) { + this.columns.forEach((column, i) => { + if (row[i] === 0) { + output[column.field] = row[i]; + } else { + output[column.field] = row[i] || this._options.defaultValue; + } + }); + } else if (typeof row === "object") { + this.columns.forEach((column) => { + if (row[column.field] === 0) { + output[column.field] = row[column.field]; + } else { + output[column.field] = + row[column.field] || this._options.defaultValue; + } + }); + } + + return output; + }); + } + + get searchResult() { + return search(this.rows, this._search, this._searchColumn); + } + + get computedRows() { + let result = [...this.searchResult]; + + if (this._options.sortOrder) { + result = sort({ + rows: result, + field: this._options.sortField, + order: this._options.sortOrder, + }); + } + + if (this._options.pagination) { + if (this._options.entries === "All") { + result = paginate({ + rows: result, + entries: result.length, + activePage: this._activePage, + }); + } else { + result = paginate({ + rows: result, + entries: this._options.entries, + activePage: this._activePage, + }); + } + } + + return result; + } + + get pages() { + if (this._options.entries === "All") { + return 1; + } + + return Math.ceil(this.searchResult.length / this._options.entries); + } + + get navigationText() { + const firstVisibleEntry = this._activePage * this._options.entries; + + if (this.searchResult.length === 0) { + return `0 ${this._options.ofText} 0`; + } + + if (this._options.entries === "All") { + return `1 - ${this.searchResult.length} ${this._options.ofText} ${this.searchResult.length}`; + } + + return `${firstVisibleEntry + 1} - ${ + this.computedRows.length + firstVisibleEntry + } ${this._options.ofText} ${this.searchResult.length}`; + } + + get tableOptions() { + return { + classes: this._classes, + columns: this.columns, + rows: this.computedRows, + noFoundMessage: this._options.noFoundMessage, + edit: this._options.edit, + loading: this._options.loading, + loaderClass: this._options.loaderClass, + loadingMessage: this._options.loadingMessage, + selectable: this._options.selectable, + multi: this._options.multi, + bordered: this._options.bordered, + borderless: this._options.borderless, + striped: this._options.striped, + hover: this._options.hover, + fixedHeader: this._options.fixedHeader, + sm: this._options.sm, + pagination: { + enable: this._options.pagination, + text: this.navigationText, + entries: this._options.entries, + entriesOptions: this._options.entriesOptions, + fullPagination: this._options.fullPagination, + rowsText: this._options.rowsText, + ofText: this._options.ofText, + allText: this._options.allText, + classes: this._classes, + }, + forceSort: this._options.forceSort, + }; + } + + // Public + + update(data, options = {}) { + if (data && data.rows) { + this._rows = data.rows; + } + + if (data && data.columns) { + this._columns = data.columns; + } + + this._clearClassList(options); + + this._options = this._getOptions({ ...this._options, ...options }); + + this._setup(); + + this._performSort(); + } + + dispose() { + if (this._selectInstance) { + this._selectInstance.dispose(); + } + + Data.removeData(this._element, DATA_KEY); + + this._removeEventListeners(); + + this._perfectScrollbar.destroy(); + + this._element = null; + } + + search(string, column) { + this._search = string; + + this._searchColumn = column; + + this._activePage = 0; + + if (this._options.pagination) { + this._toggleDisableState(); + } + + this._renderRows(); + + if (this._options.maxHeight) { + this._perfectScrollbar.element.scrollTop = 0; + + this._perfectScrollbar.update(); + } + } + + sort(column, order = "asc") { + this._options.sortOrder = order; + + if (typeof column === "string") { + this._options.sortField = this.columns.find( + (header) => header.label === column + ).field; + } else { + this._options.sortField = column.field; + } + + const icon = SelectorEngine.findOne( + `[data-te-sort="${this._options.sortField}"]`, + this._element + ); + + this._activePage = 0; + + this._toggleDisableState(); + + this._renderRows(); + + this._setActiveSortIcon(icon); + } + + setActivePage(index) { + if (index < this.pages) { + this._changeActivePage(index); + } + } + + // Private + + _getClasses(classes) { + const dataAttributes = Manipulator.getDataClassAttributes(this._element); + + classes = { + ...DefaultClasses, + ...dataAttributes, + ...classes, + }; + + typeCheckConfig(NAME, classes, DefaultClassesType); + + return classes; + } + + _changeActivePage(index) { + this._activePage = index; + + this._toggleDisableState(); + + this._renderRows(); + } + + _clearClassList(options) { + ["hover", "bordered", "borderless", "sm", "striped"].forEach((option) => { + if (this._options[option] && !options[option]) { + Manipulator.removeDataAttribute(`data-te-${option}`); + } + }); + } + + _emitSelectEvent() { + EventHandler.trigger(this._element, EVENT_SELECT, { + selectedRows: this.rows.filter( + (row) => this._selected.indexOf(row.rowIndex) !== -1 + ), + selectedIndexes: this._selected, + allSelected: this._selected.length === this.rows.length, + }); + } + + _getRows(rows = []) { + const body = SelectorEngine.findOne("tbody", this._element); + + if (!body) { + return rows; + } + + const tableRows = SelectorEngine.find("tr", body).map((row) => { + return SelectorEngine.find("td", row).map((cell) => cell.innerHTML); + }); + + return [...tableRows, ...rows]; + } + + _getColumns(columns = []) { + const head = SelectorEngine.findOne("thead", this._element); + + if (!head) { + return columns; + } + + const headerRow = SelectorEngine.findOne("tr", head); + + const headers = SelectorEngine.find("th", headerRow).map((cell) => ({ + label: cell.innerHTML, + ...Manipulator.getDataAttributes(cell), + })); + + return [...headers, ...columns]; + } + + _getCSSValue(size) { + if (typeof size === "string") { + return size; + } + + return `${size}px`; + } + + _getOptions(options) { + const config = { + ...DEFAULT_OPTIONS, + ...Manipulator.getDataAttributes(this._element), + ...options, + }; + + typeCheckConfig(NAME, config, TYPE_OPTIONS); + return config; + } + + _setActiveRows() { + SelectorEngine.find(SELECTOR_ROW, this._element).forEach((row) => { + if (this._selected.includes(Manipulator.getDataAttribute(row, "index"))) { + Manipulator.addClass(row, `active ${this._classes.selectableRow}`); + } else { + Manipulator.removeClass(row, `active ${this._classes.selectableRow}`); + } + }); + } + + _setEntries(e) { + this._options = this._getOptions({ + ...this._options, + entries: e.target.value, + }); + + if (this._activePage > this.pages - 1) { + this._activePage = this.pages - 1; + } + + this._toggleDisableState(); + + this._renderRows(); + } + + _setSelected() { + SelectorEngine.find(SELECTOR_ROW_CHECKBOX, this._element).forEach( + (checkbox) => { + const index = Manipulator.getDataAttribute(checkbox, "rowIndex"); + checkbox.checked = this._selected.includes(index); + } + ); + + this._setActiveRows(); + } + + _setActiveSortIcon(active) { + SelectorEngine.find(SELECTOR_SORT_ICON, this._element).forEach((icon) => { + const angle = + this._options.sortOrder === "desc" && icon === active ? 180 : 0; + + Manipulator.style(icon, { + transform: `rotate(${angle}deg)`, + }); + + if (icon === active && this._options.sortOrder) { + Manipulator.addClass(icon, "active"); + Manipulator.addClass(icon, `opacity-100`); + } else { + Manipulator.removeClass(icon, "active"); + Manipulator.removeClass(icon, `opacity-100`); + } + }); + } + + _setup() { + this._renderTable(); + + if (this._options.pagination) { + this._setupPagination(); + } + + if (this._options.edit) { + this._setupEditable(); + } + + if (this._options.clickableRows) { + this._setupClickableRows(); + } + + if (this._options.selectable) { + this._setupSelectable(); + } + + this._setupScroll(); + + this._setupSort(); + } + + _setupClickableRows() { + SelectorEngine.find(SELECTOR_ROW, this._element).forEach((row) => { + const index = Manipulator.getDataAttribute(row, "index"); + Manipulator.addClass(row, `cursor-pointer`); + EventHandler.on(row, "click", (e) => { + if (!SelectorEngine.matches(e.target, SELECTOR_ROW_CHECKBOX)) { + EventHandler.trigger(this._element, EVENT_ROW_CLICK, { + index, + row: this.rows[index], + }); + } + }); + }); + } + + _setupEditable() { + SelectorEngine.find(SELECTOR_ROW, this._element).forEach((row) => { + const index = Manipulator.getDataAttribute(row, "index"); + SelectorEngine.find(SELECTOR_CELL, row).forEach((cell) => { + EventHandler.on(cell, "input", (e) => this._updateRow(e, index)); + }); + }); + } + + _setupScroll() { + const datatableBody = SelectorEngine.findOne(SELECTOR_BODY, this._element); + + const style = {}; + + if (this._options.maxHeight) { + style.maxHeight = this._getCSSValue(this._options.maxHeight); + } + + if (this._options.maxWidth) { + const width = this._getCSSValue(this._options.maxWidth); + + style.maxWidth = width; + + Manipulator.style(this._element, { maxWidth: width }); + } + + Manipulator.style(datatableBody, style); + Manipulator.addClass(datatableBody, `${this._classes.scroll}`); + + if (this._options.fixedHeader) { + let headers = SelectorEngine.find(SELECTOR_HEADER, this._element); + + if (this._options.selectable) { + headers = headers.filter((header, index) => { + Manipulator.addClass( + header, + `${this._classes.fixedHeader} ${this._classes.color}` + ); + + return index !== 0; + }); + } + + headers.forEach((header, i) => { + Manipulator.addClass( + header, + `${this._classes.fixedHeader} ${this._classes.color}` + ); + + if (this.columns[i].fixed) { + Manipulator.addClass(header, `!z-40`); + } + }); + } + + this._perfectScrollbar = new PerfectScrollbar(datatableBody); + } + + _setupSort() { + SelectorEngine.find(SELECTOR_SORT_ICON, this._element).forEach((icon) => { + const field = Manipulator.getDataAttribute(icon, "sort"); + const [header] = SelectorEngine.parents(icon, "th"); + if (this.columns.sort) { + Manipulator.addClass(header, `cursor-pointer`); + } else { + return; + } + + if (field === this._options.sortField) { + this._setActiveSortIcon(icon); + } + + EventHandler.on(header, "click", () => { + if ( + this._options.sortField === field && + this._options.sortOrder === "asc" + ) { + this._options.sortOrder = "desc"; + } else if ( + this._options.sortField === field && + this._options.sortOrder === "desc" + ) { + this._options.sortOrder = this._options.forceSort ? "asc" : null; + } else { + this._options.sortOrder = "asc"; + } + + this._options.sortField = field; + + this._activePage = 0; + + this._performSort(); + + this._setActiveSortIcon(icon); + }); + }); + } + + _performSort() { + this._toggleDisableState(); + + this._renderRows(); + } + + _setupSelectable() { + this._checkboxes = SelectorEngine.find( + SELECTOR_ROW_CHECKBOX, + this._element + ); + + this._headerCheckbox = SelectorEngine.findOne( + SELECTOR_HEADER_CHECKBOX, + this._element + ); + + EventHandler.on(this._headerCheckbox, "input", (e) => + this._toggleSelectAll(e) + ); + + this._checkboxes.forEach((checkbox) => { + const rowIndex = Manipulator.getDataAttribute(checkbox, "rowIndex"); + + EventHandler.on(checkbox, "input", (e) => + this._toggleSelectRow(e, rowIndex) + ); + }); + } + + _setupPagination() { + this._paginationRight = SelectorEngine.findOne( + SELECTOR_PAGINATION_RIGHT, + this._element + ); + + this._paginationLeft = SelectorEngine.findOne( + SELECTOR_PAGINATION_LEFT, + this._element + ); + + EventHandler.on(this._paginationRight, "click", () => + this._changeActivePage(this._activePage + 1) + ); + + EventHandler.on(this._paginationLeft, "click", () => + this._changeActivePage(this._activePage - 1) + ); + + if (this._options.fullPagination) { + this._paginationStart = SelectorEngine.findOne( + SELECTOR_PAGINATION_START, + this._element + ); + + this._paginationEnd = SelectorEngine.findOne( + SELECTOR_PAGINATION_END, + this._element + ); + + EventHandler.on(this._paginationStart, "click", () => + this._changeActivePage(0) + ); + + EventHandler.on(this._paginationEnd, "click", () => + this._changeActivePage(this.pages - 1) + ); + } + + this._toggleDisableState(); + + this._setupPaginationSelect(); + } + + _setupPaginationSelect() { + this._select = SelectorEngine.findOne(SELECTOR_SELECT, this._element); + + this._selectInstance = new Select(this._select); + + EventHandler.on(this._select, "valueChange.te.select", (e) => + this._setEntries(e) + ); + } + + _removeEventListeners() { + if (this._options.pagination) { + EventHandler.off(this._paginationRight, "click"); + + EventHandler.off(this._paginationLeft, "click"); + + EventHandler.off(this._select, "valueChange.te.select"); + + if (this._options.fullPagination) { + EventHandler.off(this._paginationStart, "click"); + + EventHandler.off(this._paginationEnd, "click"); + } + } + + if (this._options.edit) { + SelectorEngine.find(SELECTOR_CELL, this._element).forEach((cell) => { + EventHandler.off(cell, "input"); + }); + } + + if (this._options.clickableRows) { + SelectorEngine.find(SELECTOR_ROW, this._element).forEach((row) => { + EventHandler.off(row, "click"); + }); + } + + SelectorEngine.find(SELECTOR_SORT_ICON, this._element).forEach((icon) => { + const [header] = SelectorEngine.parents(icon, "th"); + + EventHandler.off(header, "click"); + }); + + if (this._options.selectable) { + EventHandler.off(this._headerCheckbox, "input"); + + this._checkboxes.forEach((checkbox) => { + EventHandler.off(checkbox, "input"); + }); + } + } + + _renderTable() { + this._element.innerHTML = tableTemplate(this.tableOptions).table; + + this._formatCells(); + + EventHandler.trigger(this._element, EVENT_RENDER); + } + + _renderRows() { + const body = SelectorEngine.findOne("tbody", this._element); + + if (this._options.pagination) { + const navigation = SelectorEngine.findOne( + SELECTOR_PAGINATION_NAV, + this._element + ); + navigation.innerText = this.navigationText; + } + + body.innerHTML = tableTemplate(this.tableOptions).rows; + + this._formatCells(); + + if (this._options.edit) { + this._setupEditable(); + } + + if (this._options.selectable) { + this._setupSelectable(); + + this._setSelected(); + } + + if (this._options.clickableRows) { + this._setupClickableRows(); + } + + EventHandler.trigger(this._element, EVENT_RENDER); + } + + _formatCells() { + const rows = SelectorEngine.find(SELECTOR_ROW, this._element); + + rows.forEach((row) => { + const index = Manipulator.getDataAttribute(row, "index"); + + const cells = SelectorEngine.find(SELECTOR_CELL, row); + + cells.forEach((cell) => { + const field = Manipulator.getDataAttribute(cell, "field"); + + const column = this.columns.find((column) => column.field === field); + + if (column && column.format !== null) { + column.format(cell, this.rows[index][field]); + } + }); + }); + } + + _toggleDisableState() { + if (this._options.pagination === false) { + return; + } + if (this._activePage === 0 || this._options.loading) { + this._paginationLeft.setAttribute("disabled", ""); + + if (this._options.fullPagination) { + this._paginationStart.setAttribute("disabled", ""); + } + } else { + this._paginationLeft.removeAttribute("disabled"); + if (this._options.fullPagination) { + this._paginationStart.removeAttribute("disabled"); + } + } + if ( + this._activePage === this.pages - 1 || + this._options.loading || + this.pages === 0 + ) { + this._paginationRight.setAttribute("disabled", ""); + if (this._options.fullPagination) { + this._paginationEnd.setAttribute("disabled", ""); + } + } else { + this._paginationRight.removeAttribute("disabled"); + if (this._options.fullPagination) { + this._paginationEnd.removeAttribute("disabled"); + } + } + } + + _toggleSelectAll(e) { + if (e.target.checked) { + this._selected = this.rows.map((row) => row.rowIndex); + } else this._selected = []; + + this._setSelected(); + + this._emitSelectEvent(); + } + + _toggleSelectRow(e, rowIndex) { + if (e.target.checked) { + if (this._options.multi && !this._selected.includes(rowIndex)) { + this._selected = [...this._selected, rowIndex]; + } else { + this._selected = [rowIndex]; + + this._checkboxes.forEach((checkbox) => { + if (checkbox !== e.target) { + checkbox.checked = false; + } + }); + } + } else { + this._selected = this._selected.filter((index) => index !== rowIndex); + } + if (this._options.multi && !e.target.checked) { + this._headerCheckbox.checked = false; + } + + this._setActiveRows(); + + this._emitSelectEvent(); + } + + _updateRow(event, index) { + const field = Manipulator.getDataAttribute(event.target, "field"); + + const value = event.target.textContent; + + const row = this._rows[index]; + + if (Array.isArray(row)) { + const column = this.columns.find((column) => { + return column.field === field; + }); + + const columnIndex = column.columnIndex; + + row[columnIndex] = value; + } else { + row[field] = value; + } + + EventHandler.trigger(this._element, EVENT_UPDATE, { + rows: this._rows, + columns: this._columns, + }); + } + + static jQueryInterface(config, param1, param2) { + return this.each(function () { + let data = Data.getData(this, DATA_KEY); + const _config = typeof config === "object" && config; + + if (!data && /dispose/.test(config)) { + return; + } + + if (!data) { + data = new Datatable(this, _config, param1); + } + + if (typeof config === "string") { + if (typeof data[config] === "undefined") { + throw new TypeError(`No method named "${config}"`); + } + + data[config](param1, param2); + } + }); + } + + static getInstance(element) { + return Data.getData(element, DATA_KEY); + } + + static getOrCreateInstance(element, config = {}) { + return ( + this.getInstance(element) || + new this(element, typeof config === "object" ? config : null) + ); + } +} + +export default Datatable; diff --git a/src/js/data/datatables/util.js b/src/js/data/datatables/util.js new file mode 100644 index 000000000..43365742d --- /dev/null +++ b/src/js/data/datatables/util.js @@ -0,0 +1,62 @@ +const sort = ({ rows, field, order }) => { + const sorted = rows.sort((a, b) => { + let fieldA = a[field]; + let fieldB = b[field]; + + if (typeof fieldA === "string") { + fieldA = fieldA.toLowerCase(); + } + if (typeof fieldB === "string") { + fieldB = fieldB.toLowerCase(); + } + + if (fieldA < fieldB) { + return order === "desc" ? 1 : -1; + } + if (fieldA > fieldB) { + return order === "desc" ? -1 : 1; + } + return 0; + }); + + return sorted; +}; + +const search = (rows, search, column) => { + if (!search) return rows; + + const match = (entry) => { + const div = document.createElement("div"); + div.innerHTML = entry; + entry = div.textContent || div.innerText || ""; + + return entry.toString().toLowerCase().match(search.toLowerCase()); + }; + + return rows.filter((row) => { + if (column && typeof column === "string") { + return match(row[column]); + } + + let values = Object.values(row); + + if (column && Array.isArray(column)) { + values = Object.keys(row) + .filter((key) => column.includes(key)) + .map((key) => row[key]); + } + + return ( + values.filter((value) => { + return match(value); + }).length > 0 + ); + }); +}; + +const paginate = ({ rows, entries, activePage }) => { + const firstVisibleEntry = activePage * entries; + return rows.slice(firstVisibleEntry, firstVisibleEntry + Number(entries)); +}; + +export { sort, search, paginate }; diff --git a/src/js/index.es.js b/src/js/index.es.js index 206d4aab1..25accaee8 100644 --- a/src/js/index.es.js +++ b/src/js/index.es.js @@ -33,6 +33,7 @@ import ChipsInput from "./components/chips"; import Chip from "./components/chips/chip"; import Chart from "./data/chart/charts"; import PerfectScrollbar from "./methods/perfect-scrollbar"; +import Datatable from "./data/datatables/index"; import initTE from "./autoinit/index"; export { @@ -60,5 +61,6 @@ export { Input, Chart, PerfectScrollbar, + Datatable, initTE, }; diff --git a/src/js/index.umd.js b/src/js/index.umd.js index f40dd29b4..6d1b777a3 100644 --- a/src/js/index.umd.js +++ b/src/js/index.umd.js @@ -33,6 +33,7 @@ import ChipsInput from "./components/chips"; import Chip from "./components/chips/chip"; import Chart from "./data/chart/charts"; import PerfectScrollbar from "./methods/perfect-scrollbar"; +import Datatable from "./data/datatables/index"; import initTE from "./autoinit/index"; const te = { @@ -60,6 +61,7 @@ const te = { Input, PerfectScrollbar, Chart, + Datatable, }; initTE(te); @@ -89,5 +91,6 @@ export { Input, Chart, PerfectScrollbar, + Datatable, initTE, }; diff --git a/src/js/plugin.cjs b/src/js/plugin.cjs index 3f2bdf447..02050c9c2 100644 --- a/src/js/plugin.cjs +++ b/src/js/plugin.cjs @@ -274,6 +274,10 @@ module.exports = plugin(() => {}, { transform: "scale(1)", }, }, + progress: { + "0%": { transform: "translateX(-45%)" }, + "100%": { transform: "translateX(100%)" }, + }, }, colors: { primary: { From 37e5f04ff40962659e2b4e7abcfc055844172b1c Mon Sep 17 00:00:00 2001 From: igor_przybysz Date: Tue, 18 Jul 2023 12:31:10 +0200 Subject: [PATCH 2/4] Make corrections --- .../docs/standard/data/datatables/a.html | 122 +++ .../docs/standard/data/datatables/index.html | 911 ++++++++++++++++-- src/js/autoinit/autoinitCallbacks.js | 12 - src/js/autoinit/index.js | 3 - src/js/data/datatables/html/columns.js | 18 +- src/js/data/datatables/html/pagination.js | 53 +- src/js/data/datatables/html/rows.js | 13 +- src/js/data/datatables/html/table.js | 11 +- src/js/data/datatables/index.js | 119 ++- 9 files changed, 1084 insertions(+), 178 deletions(-) diff --git a/site/content/docs/standard/data/datatables/a.html b/site/content/docs/standard/data/datatables/a.html index e6a1647a8..836c1a0cd 100644 --- a/site/content/docs/standard/data/datatables/a.html +++ b/site/content/docs/standard/data/datatables/a.html @@ -514,6 +514,104 @@

    Via JavaScript

    Shows/hides the pagination panel. + + + paginationEndIconTemplate + + + String + + + <svg xmlns="http://www.w3.org/2000/svg" fill="none" + viewBox="0 0 24 24" stroke-width="1.5" + stroke="currentColor" class="w-4 h-4"> <path + stroke-linecap="round" stroke-linejoin="round" d="M11.25 + 4.5l7.5 7.5-7.5 7.5m-6-15l7.5 7.5-7.5 + 7.5"/></svg> + + + Changes pagination end button template. + + + + + paginationLeftIconTemplate + + + String + + + <svg xmlns="http://www.w3.org/2000/svg" fill="none" + viewBox="0 0 24 24" stroke-width="1.5" + stroke="currentColor" class="w-4 h-4"> <path + stroke-linecap="round" stroke-linejoin="round" d="M15.75 + 19.5L8.25 12l7.5-7.5" /></svg> + + + Changes pagination left button template. + + + + + paginationRightIconTemplate + + + String + + + <svg xmlns="http://www.w3.org/2000/svg" fill="none" + viewBox="0 0 24 24" stroke-width="1.5" + stroke="currentColor" class="w-4 h-4"> <path + stroke-linecap="round" stroke-linejoin="round" d="M8.25 + 4.5l7.5 7.5-7.5 7.5" /></svg> + + + Changes pagination right button template. + + + + + paginationStartIconTemplate + + + String + + + <svg xmlns="http://www.w3.org/2000/svg" + fill="currentColor" viewBox="0 0 24 24" stroke-width="1.5" + stroke="currentColor" class="w-4 h-4"> <path + stroke-linecap="round" stroke-linejoin="round" d="M18.75 + 19.5l-7.5-7.5 7.5-7.5m-6 15L5.25 12l7.5-7.5" + /></svg> + + + Changes pagination start button template. + + Via JavaScript Enables selecting rows with checkboxes. + + + sortIconTemplate + + + String + + + <svg xmlns="http://www.w3.org/2000/svg" + fill="currentColor" viewBox="0 0 24 24" stroke-width="2" + stroke="currentColor"> <path stroke-linecap="round" + stroke-linejoin="round" d="M4.5 10.5L12 3m0 0l7.5 7.5M12 + 3v18" /> </svg> + + + Changes sort icon template. + +
    - {{< twsnippet/wrapper "HTML, javascript" >}} + {{< twsnippet/wrapper "HTML,javascript" >}} {{< twsnippet/code active=true lang="HTML" >}}
    @@ -312,13 +312,12 @@ {{< /twsnippet/code >}} {{< twsnippet/code lang="js" >}} // Initialization for ES Users - import { + import { Datatable, - Select, initTE, - } from "tw-elements"; + } from "tw-elements"; - initTE({ Datatable, Select }); + initTE({ Datatable }); {{< /twsnippet/code >}} {{< /twsnippet/wrapper >}} @@ -355,11 +354,19 @@ @@ -42,13 +42,11 @@ const columns = ( : "" }" scope="col">${ column.sort - ? `
    - - ` + } ${loading ? "invisible" : ""}" data-te-sort="${ + column.field + }" ${ATTR_SORT_ICON}>${sortIconTemplate}` : "" } ${ column.label diff --git a/src/js/data/datatables/html/pagination.js b/src/js/data/datatables/html/pagination.js index c4cb72de8..62e335ef6 100644 --- a/src/js/data/datatables/html/pagination.js +++ b/src/js/data/datatables/html/pagination.js @@ -1,15 +1,28 @@ /* eslint-disable indent */ +const ATTR_SELECT = "data-te-datatable-select-ref"; +const ATTR_PAGINATION_NAV = "data-te-datatable-pagination-nav-ref"; +const ATTR_PAGINATION_RIGHT = "data-te-datatable-pagination-right-ref"; +const ATTR_PAGINATION_LEFT = "data-te-datatable-pagination-left-ref"; +const ATTR_PAGINATION_START = "data-te-datatable-pagination-start-ref"; +const ATTR_PAGINATION_END = "data-te-datatable-pagination-end-ref"; + const pagination = ( - { text, entries, entriesOptions, fullPagination, rowsText, allText, classes }, + { + text, + entries, + entriesOptions, + fullPagination, + rowsText, + allText, + paginationStartIconTemplate, + paginationLeftIconTemplate, + paginationRightIconTemplate, + paginationEndIconTemplate, + classes, + }, loading, bordered ) => { - const SELECTOR_SELECT = "data-te-datatable-select-ref"; - const SELECTOR_PAGINATION_NAV = "data-te-datatable-pagination-nav-ref"; - const SELECTOR_PAGINATION_RIGHT = "data-te-datatable-pagination-right-ref"; - const SELECTOR_PAGINATION_LEFT = "data-te-datatable-pagination-left-ref"; - const SELECTOR_PAGINATION_START = "data-te-datatable-pagination-start-ref"; - const SELECTOR_PAGINATION_END = "data-te-datatable-pagination-end-ref"; const options = entriesOptions .map((option) => { if (option === "All") { @@ -35,44 +48,38 @@ const pagination = ( loading ? `${classes.loadingPaginationSelectWrapper}` : "" }">
    + }" ${ATTR_PAGINATION_NAV}> ${text}
    ${ fullPagination - ? `` : "" } ${ fullPagination - ? `` : "" } diff --git a/src/js/data/datatables/html/rows.js b/src/js/data/datatables/html/rows.js index 15eb35a37..eb28c1afa 100644 --- a/src/js/data/datatables/html/rows.js +++ b/src/js/data/datatables/html/rows.js @@ -1,4 +1,8 @@ /* eslint-disable indent */ +const ATTR_ROW = "data-te-datatable-row-ref"; +const ATTR_ROW_CHECKBOX = "data-te-datatable-row-checkbox-ref"; +const ATTR_CELL = "data-te-datatable-cell-ref"; + const rows = ({ rows, columns, @@ -14,9 +18,6 @@ const rows = ({ classes, }) => { const rowsTemplate = rows.map((row) => { - const SELECTOR_ROW = "data-te-datatable-row-ref"; - const SELECTOR_ROW_CHECKBOX = "data-te-datatable-row-checkbox-ref"; - const SELECTOR_CELL = "data-te-datatable-cell-ref"; const checkbox = `
    `; const innerRow = columns @@ -59,7 +60,7 @@ const rows = ({ bordered ? `${classes.tableBordered}` : "" } ${sm ? `${classes.sm}` : ""} ${ column.fixed ? `${classes.fixedHeader} ${classes.color}` : "" - }" ${SELECTOR_CELL} data-te-field="${column.field}" ${ + }" ${ATTR_CELL} data-te-field="${column.field}" ${ edit && 'contenteditable="true"' }>${row[column.field]}`; }) @@ -71,7 +72,7 @@ const rows = ({ borderless ? `${classes.borderless}` : "" } ${hover ? `${classes.hoverRow}` : ""}" data-te-index="${ row.rowIndex - }" ${SELECTOR_ROW}>${selectable ? checkbox : ""}${innerRow}`; + }" ${ATTR_ROW}>${selectable ? checkbox : ""}${innerRow}`; }); return rows.length > 0 || loading diff --git a/src/js/data/datatables/html/table.js b/src/js/data/datatables/html/table.js index 16e7abc60..3c8fc7c63 100644 --- a/src/js/data/datatables/html/table.js +++ b/src/js/data/datatables/html/table.js @@ -3,6 +3,9 @@ import paginationTemplate from "./pagination"; import generateColumns from "./columns"; import generateRows from "./rows"; +const ATTR_BODY = "data-te-datatable-inner-ref"; +const ATTR_HEADER = "data-te-datatable-header-ref"; + const tableTemplate = ({ columns, rows, @@ -19,10 +22,9 @@ const tableTemplate = ({ hover, fixedHeader, sm, + sortIconTemplate, classes, }) => { - const SELECTOR_BODY = "data-te-datatable-inner-ref"; - const SELECTOR_HEADER = "data-te-datatable-header-ref"; const rowsTemplate = generateRows({ rows, columns, @@ -44,17 +46,18 @@ const tableTemplate = ({ bordered, sm, loading, + sortIconTemplate, classes ); const table = ` -
    +
    @@ -19,8 +20,7 @@ const columns = ( class="${classes.checkboxHeader}" type="checkbox" value="" - id="checkboxDefault" - ${SELECTOR_HEADER_CHECKBOX} + ${ATTR_HEADER_CHECKBOX} /> + data-te-row-index="${row.rowIndex}" ${ATTR_ROW_CHECKBOX}/>
    + }" ${ATTR_HEADER}> ${columnsTemplate} diff --git a/src/js/data/datatables/index.js b/src/js/data/datatables/index.js index 6118a1b26..bfa172944 100644 --- a/src/js/data/datatables/index.js +++ b/src/js/data/datatables/index.js @@ -1,3 +1,14 @@ +/* +-------------------------------------------------------------------------- +Tailwind Elements is an open-source UI kit of advanced components for TailwindCSS. +Copyright © 2023 MDBootstrap.com + +Unless a custom, individually assigned license has been granted, this program is free software: you can redistribute it and/or modify it under the terms of the GNU Affero General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. +In addition, a custom license may be available upon request, subject to the terms and conditions of that license. Please contact tailwind@mdbootstrap.com for more information on obtaining a custom license. +This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Affero General Public License for more details. +-------------------------------------------------------------------------- +*/ + import PerfectScrollbar from "../../methods/perfect-scrollbar"; import { typeCheckConfig } from "../../util/index"; import Data from "../../dom/data"; @@ -19,25 +30,41 @@ const ATTR_NAME = `data-te-${NAME}`; const DATA_KEY = `te.${NAME}`; const EVENT_KEY = `.${DATA_KEY}`; -const SELECTOR_BODY = `[${ATTR_NAME}-inner-ref]`; -const SELECTOR_CELL = `[${ATTR_NAME}-cell-ref]`; -const SELECTOR_HEADER = `[${ATTR_NAME}-header-ref]`; -const SELECTOR_HEADER_CHECKBOX = `[${ATTR_NAME}-header-checkbox-ref]`; -const SELECTOR_PAGINATION_RIGHT = `[${ATTR_NAME}-pagination-right-ref]`; -const SELECTOR_PAGINATION_LEFT = `[${ATTR_NAME}-pagination-left-ref]`; -const SELECTOR_PAGINATION_START = `[${ATTR_NAME}-pagination-start-ref]`; -const SELECTOR_PAGINATION_END = `[${ATTR_NAME}-pagination-end-ref]`; -const SELECTOR_PAGINATION_NAV = `[${ATTR_NAME}-pagination-nav-ref]`; -const SELECTOR_SELECT = `[${ATTR_NAME}-select-ref]`; -const SELECTOR_SORT_ICON = `[${ATTR_NAME}-sort-icon-ref]`; -const SELECTOR_ROW = `[${ATTR_NAME}-row-ref]`; -const SELECTOR_ROW_CHECKBOX = `[${ATTR_NAME}-row-checkbox-ref]`; +const ATTR_BODY = `[${ATTR_NAME}-inner-ref]`; +const ATTR_CELL = `[${ATTR_NAME}-cell-ref]`; +const ATTR_HEADER = `[${ATTR_NAME}-header-ref]`; +const ATTR_HEADER_CHECKBOX = `[${ATTR_NAME}-header-checkbox-ref]`; +const ATTR_PAGINATION_RIGHT = `[${ATTR_NAME}-pagination-right-ref]`; +const ATTR_PAGINATION_LEFT = `[${ATTR_NAME}-pagination-left-ref]`; +const ATTR_PAGINATION_START = `[${ATTR_NAME}-pagination-start-ref]`; +const ATTR_PAGINATION_END = `[${ATTR_NAME}-pagination-end-ref]`; +const ATTR_PAGINATION_NAV = `[${ATTR_NAME}-pagination-nav-ref]`; +const ATTR_SELECT = `[${ATTR_NAME}-select-ref]`; +const ATTR_SORT_ICON = `[${ATTR_NAME}-sort-icon-ref]`; +const ATTR_ROW = `[${ATTR_NAME}-row-ref]`; +const ATTR_ROW_CHECKBOX = `[${ATTR_NAME}-row-checkbox-ref]`; const EVENT_SELECT = `selectRows${EVENT_KEY}`; const EVENT_RENDER = `render${EVENT_KEY}`; const EVENT_ROW_CLICK = `rowClick${EVENT_KEY}`; const EVENT_UPDATE = `update${EVENT_KEY}`; +const sortIconTemplate = ` + +`; +const paginationStartIconTemplate = ` + +`; +const paginationLeftIconTemplate = ` + +`; +const paginationRightIconTemplate = ` + +`; +const paginationEndIconTemplate = ` + +`; + const BORDER_COLOR_CLASSES = "border-neutral-200 dark:border-neutral-500"; const BORDERLESS_CLASSES = "border-none"; const CHECKBOX_HEADER_CLASSES = @@ -133,6 +160,11 @@ const TYPE_OPTIONS = { ofText: "string", allText: "string", forceSort: "boolean", + sortIconTemplate: "string", + paginationStartIconTemplate: "string", + paginationEndIconTemplate: "string", + paginationLeftIconTemplate: "string", + paginationRightIconTemplate: "string", }; const DEFAULT_OPTIONS = { @@ -162,6 +194,11 @@ const DEFAULT_OPTIONS = { ofText: "of", allText: "All", forceSort: false, + sortIconTemplate: sortIconTemplate, + paginationStartIconTemplate: paginationStartIconTemplate, + paginationEndIconTemplate: paginationEndIconTemplate, + paginationLeftIconTemplate: paginationLeftIconTemplate, + paginationRightIconTemplate: paginationRightIconTemplate, }; const TYPE_COLUMN_FIELDS = { @@ -453,6 +490,7 @@ class Datatable { hover: this._options.hover, fixedHeader: this._options.fixedHeader, sm: this._options.sm, + sortIconTemplate: this._options.sortIconTemplate, pagination: { enable: this._options.pagination, text: this.navigationText, @@ -462,6 +500,10 @@ class Datatable { rowsText: this._options.rowsText, ofText: this._options.ofText, allText: this._options.allText, + paginationStartIconTemplate: this._options.paginationStartIconTemplate, + paginationLeftIconTemplate: this._options.paginationLeftIconTemplate, + paginationRightIconTemplate: this._options.paginationRightIconTemplate, + paginationEndIconTemplate: this._options.paginationEndIconTemplate, classes: this._classes, }, forceSort: this._options.forceSort, @@ -646,7 +688,7 @@ class Datatable { } _setActiveRows() { - SelectorEngine.find(SELECTOR_ROW, this._element).forEach((row) => { + SelectorEngine.find(ATTR_ROW, this._element).forEach((row) => { if (this._selected.includes(Manipulator.getDataAttribute(row, "index"))) { Manipulator.addClass(row, `active ${this._classes.selectableRow}`); } else { @@ -671,7 +713,7 @@ class Datatable { } _setSelected() { - SelectorEngine.find(SELECTOR_ROW_CHECKBOX, this._element).forEach( + SelectorEngine.find(ATTR_ROW_CHECKBOX, this._element).forEach( (checkbox) => { const index = Manipulator.getDataAttribute(checkbox, "rowIndex"); checkbox.checked = this._selected.includes(index); @@ -682,7 +724,7 @@ class Datatable { } _setActiveSortIcon(active) { - SelectorEngine.find(SELECTOR_SORT_ICON, this._element).forEach((icon) => { + SelectorEngine.find(ATTR_SORT_ICON, this._element).forEach((icon) => { const angle = this._options.sortOrder === "desc" && icon === active ? 180 : 0; @@ -691,10 +733,8 @@ class Datatable { }); if (icon === active && this._options.sortOrder) { - Manipulator.addClass(icon, "active"); Manipulator.addClass(icon, `opacity-100`); } else { - Manipulator.removeClass(icon, "active"); Manipulator.removeClass(icon, `opacity-100`); } }); @@ -725,11 +765,11 @@ class Datatable { } _setupClickableRows() { - SelectorEngine.find(SELECTOR_ROW, this._element).forEach((row) => { + SelectorEngine.find(ATTR_ROW, this._element).forEach((row) => { const index = Manipulator.getDataAttribute(row, "index"); Manipulator.addClass(row, `cursor-pointer`); EventHandler.on(row, "click", (e) => { - if (!SelectorEngine.matches(e.target, SELECTOR_ROW_CHECKBOX)) { + if (!SelectorEngine.matches(e.target, ATTR_ROW_CHECKBOX)) { EventHandler.trigger(this._element, EVENT_ROW_CLICK, { index, row: this.rows[index], @@ -740,16 +780,16 @@ class Datatable { } _setupEditable() { - SelectorEngine.find(SELECTOR_ROW, this._element).forEach((row) => { + SelectorEngine.find(ATTR_ROW, this._element).forEach((row) => { const index = Manipulator.getDataAttribute(row, "index"); - SelectorEngine.find(SELECTOR_CELL, row).forEach((cell) => { + SelectorEngine.find(ATTR_CELL, row).forEach((cell) => { EventHandler.on(cell, "input", (e) => this._updateRow(e, index)); }); }); } _setupScroll() { - const datatableBody = SelectorEngine.findOne(SELECTOR_BODY, this._element); + const datatableBody = SelectorEngine.findOne(ATTR_BODY, this._element); const style = {}; @@ -769,7 +809,7 @@ class Datatable { Manipulator.addClass(datatableBody, `${this._classes.scroll}`); if (this._options.fixedHeader) { - let headers = SelectorEngine.find(SELECTOR_HEADER, this._element); + let headers = SelectorEngine.find(ATTR_HEADER, this._element); if (this._options.selectable) { headers = headers.filter((header, index) => { @@ -798,7 +838,7 @@ class Datatable { } _setupSort() { - SelectorEngine.find(SELECTOR_SORT_ICON, this._element).forEach((icon) => { + SelectorEngine.find(ATTR_SORT_ICON, this._element).forEach((icon) => { const field = Manipulator.getDataAttribute(icon, "sort"); const [header] = SelectorEngine.parents(icon, "th"); if (this.columns.sort) { @@ -844,13 +884,10 @@ class Datatable { } _setupSelectable() { - this._checkboxes = SelectorEngine.find( - SELECTOR_ROW_CHECKBOX, - this._element - ); + this._checkboxes = SelectorEngine.find(ATTR_ROW_CHECKBOX, this._element); this._headerCheckbox = SelectorEngine.findOne( - SELECTOR_HEADER_CHECKBOX, + ATTR_HEADER_CHECKBOX, this._element ); @@ -869,12 +906,12 @@ class Datatable { _setupPagination() { this._paginationRight = SelectorEngine.findOne( - SELECTOR_PAGINATION_RIGHT, + ATTR_PAGINATION_RIGHT, this._element ); this._paginationLeft = SelectorEngine.findOne( - SELECTOR_PAGINATION_LEFT, + ATTR_PAGINATION_LEFT, this._element ); @@ -888,12 +925,12 @@ class Datatable { if (this._options.fullPagination) { this._paginationStart = SelectorEngine.findOne( - SELECTOR_PAGINATION_START, + ATTR_PAGINATION_START, this._element ); this._paginationEnd = SelectorEngine.findOne( - SELECTOR_PAGINATION_END, + ATTR_PAGINATION_END, this._element ); @@ -912,7 +949,7 @@ class Datatable { } _setupPaginationSelect() { - this._select = SelectorEngine.findOne(SELECTOR_SELECT, this._element); + this._select = SelectorEngine.findOne(ATTR_SELECT, this._element); this._selectInstance = new Select(this._select); @@ -937,18 +974,18 @@ class Datatable { } if (this._options.edit) { - SelectorEngine.find(SELECTOR_CELL, this._element).forEach((cell) => { + SelectorEngine.find(ATTR_CELL, this._element).forEach((cell) => { EventHandler.off(cell, "input"); }); } if (this._options.clickableRows) { - SelectorEngine.find(SELECTOR_ROW, this._element).forEach((row) => { + SelectorEngine.find(ATTR_ROW, this._element).forEach((row) => { EventHandler.off(row, "click"); }); } - SelectorEngine.find(SELECTOR_SORT_ICON, this._element).forEach((icon) => { + SelectorEngine.find(ATTR_SORT_ICON, this._element).forEach((icon) => { const [header] = SelectorEngine.parents(icon, "th"); EventHandler.off(header, "click"); @@ -976,7 +1013,7 @@ class Datatable { if (this._options.pagination) { const navigation = SelectorEngine.findOne( - SELECTOR_PAGINATION_NAV, + ATTR_PAGINATION_NAV, this._element ); navigation.innerText = this.navigationText; @@ -1004,12 +1041,12 @@ class Datatable { } _formatCells() { - const rows = SelectorEngine.find(SELECTOR_ROW, this._element); + const rows = SelectorEngine.find(ATTR_ROW, this._element); rows.forEach((row) => { const index = Manipulator.getDataAttribute(row, "index"); - const cells = SelectorEngine.find(SELECTOR_CELL, row); + const cells = SelectorEngine.find(ATTR_CELL, row); cells.forEach((cell) => { const field = Manipulator.getDataAttribute(cell, "field"); From a8169d8e0dcb4512a068021fe703d4fdb2acd3e9 Mon Sep 17 00:00:00 2001 From: igor_przybysz Date: Wed, 19 Jul 2023 07:59:58 +0200 Subject: [PATCH 3/4] Make corrections #2 --- demo/sites/data/datatables.html | 1 - .../docs/standard/data/datatables/a.html | 24 +++++++++---------- .../standard/data/datatables/index-js.html | 1 - .../docs/standard/data/datatables/index.html | 2 -- src/js/data/datatables/html/columns.js | 2 +- src/js/data/datatables/html/pagination.js | 8 +++---- src/js/data/datatables/html/rows.js | 1 - src/js/data/datatables/index.js | 18 +++++++------- 8 files changed, 26 insertions(+), 31 deletions(-) diff --git a/demo/sites/data/datatables.html b/demo/sites/data/datatables.html index e4a0ee176..1b812f8d5 100644 --- a/demo/sites/data/datatables.html +++ b/demo/sites/data/datatables.html @@ -1048,7 +1048,6 @@

    colorClass.forEach((className) => { cell.classList.add(className); }); - cell.classList.add("font-medium"); }; const columns = [ diff --git a/site/content/docs/standard/data/datatables/a.html b/site/content/docs/standard/data/datatables/a.html index 836c1a0cd..aaefb79aa 100644 --- a/site/content/docs/standard/data/datatables/a.html +++ b/site/content/docs/standard/data/datatables/a.html @@ -600,8 +600,8 @@

    Via JavaScript

    `; diff --git a/src/js/data/datatables/index.js b/src/js/data/datatables/index.js index bfa172944..23279c4a6 100644 --- a/src/js/data/datatables/index.js +++ b/src/js/data/datatables/index.js @@ -49,10 +49,10 @@ const EVENT_RENDER = `render${EVENT_KEY}`; const EVENT_ROW_CLICK = `rowClick${EVENT_KEY}`; const EVENT_UPDATE = `update${EVENT_KEY}`; -const sortIconTemplate = ` +const sortIconTemplate = ` `; -const paginationStartIconTemplate = ` +const paginationStartIconTemplate = ` `; const paginationLeftIconTemplate = ` @@ -76,7 +76,7 @@ const CHECKBOX_ROW_CLASSES = const CHECKBOX_ROW_WRAPPER_CLASSES = "mb-[0.125rem] min-h-[1.5rem] pl-[1.5rem] ml-3 flex items-center"; const COLOR_CLASSES = "bg-white dark:bg-neutral-800"; -const COLUMNS_CLASSES = "py-4 text-clip overflow-hidden"; +const COLUMNS_CLASSES = "py-4 pl-1 text-clip overflow-hidden text-[#212529]"; const EDIT_CLASSES = "focus:outline-none"; const FIXED_HEADER_CLASSES = "sticky top-0 z-30"; const FIXED_HEADER_BODY_CLASSES = "sticky z-10 bg-inherit"; @@ -99,7 +99,7 @@ const NO_FOUND_MESSAGE_CLASSES = "pl-2 py-3 font-light text-sm dark:text-neutral-300"; const NO_FOUND_MESSAGE_WRAPPER_CLASSES = "border-b"; const PAGINATION_CLASSES = - "flex md:flex-row justify-end items-center py-2 space-x-4 text-sm flex-col"; + "flex md:flex-row justify-end items-center py-2 space-x-4 text-sm flex-col leading-[1.6]"; const PAGINATION_BORDERED_CLASSES = "border border-t-0"; const PAGINATION_BUTTONS_WRAPPER_CLASSES = "order-1 my-3 md:order-none md:my-0 md:pr-1"; @@ -117,21 +117,21 @@ const ROW_CLASSES = "border-b"; const ROW_ANIMATION_CLASSES = "transition ease-in-out duration-300 motion-reduce:transition-none"; const ROW_ITEM_CLASSES = - "whitespace-nowrap text-clip overflow-hidden px-6 py-4"; + "whitespace-nowrap text-clip overflow-hidden px-[1.4rem] py-4"; const SCROLL_CLASSES = "relative"; const SELECTABLE_ROW_CLASSES = "!bg-neutral-100 dark:!bg-neutral-600"; const SELECT_ITEMS_WRAPPER_CLASSES = "flex items-center space-x-4 order-3 md:order-none"; -const SELECT_WRAPPER_CLASSES = "w-20"; +const SELECT_WRAPPER_CLASSES = "w-[70px]"; const SM_CLASSES = "!py-2"; const SORT_ICON_CLASSES = - "w-5 h-5 pb-1 mr-1 opacity-0 text-neutral-500 group-hover:opacity-100 transition hover:ease-in-out transform ease-linear duration-300 motion-reduce:transition-none dark:text-neutral-400"; + "w-[15px] h-[10px] origin-bottom font-black mr-1 opacity-0 text-neutral-500 group-hover:opacity-100 transition hover:ease-in-out transform ease-linear duration-300 motion-reduce:transition-none dark:text-neutral-400"; const SORT_ICON_WRAPPER_CLASSES = "flex flex-row group"; const STRIPED_CLASSES = "[&:nth-child(odd)]:bg-neutral-50 [&:nth-child(odd)]:dark:bg-neutral-700"; const TABLE_BORDERED_CLASSES = "border"; -const TABLE_HEADER_CLASSES = "border-b font-medium"; -const TABLE_CLASSES = "text-left text-sm font-light w-full"; +const TABLE_HEADER_CLASSES = "border-b font-normal px-[1.4rem]"; +const TABLE_CLASSES = "text-left text-sm font-light w-full leading-[1.6]"; const TYPE_OPTIONS = { bordered: "boolean", From fb27af1138e1800fb1f5bbd86d88d590ce8adae1 Mon Sep 17 00:00:00 2001 From: Bartosz Cylwik Date: Wed, 19 Jul 2023 12:09:54 +0200 Subject: [PATCH 4/4] Add info about license, small update in datatable --- site/content/docs/standard/data/datatables/a.html | 1 + src/js/data/chart/chartDefaults.js | 11 +++++++++++ src/js/data/chart/charts.js | 11 +++++++++++ src/js/data/datatables/html/columns.js | 11 +++++++++++ src/js/data/datatables/html/pagination.js | 11 +++++++++++ src/js/data/datatables/html/rows.js | 11 +++++++++++ src/js/data/datatables/html/table.js | 11 +++++++++++ src/js/data/datatables/index.js | 3 ++- src/js/data/datatables/util.js | 11 +++++++++++ 9 files changed, 80 insertions(+), 1 deletion(-) diff --git a/site/content/docs/standard/data/datatables/a.html b/site/content/docs/standard/data/datatables/a.html index aaefb79aa..6911437ff 100644 --- a/site/content/docs/standard/data/datatables/a.html +++ b/site/content/docs/standard/data/datatables/a.html @@ -1150,6 +1150,7 @@

    Via JavaScript

    <svg xmlns="http://www.w3.org/2000/svg" - fill="currentColor" viewBox="0 0 24 24" stroke-width="1.5" + ><svg xmlns="http://www.w3.org/2000/svg" fill="none" + viewBox="0 0 24 24" stroke-width="1.5" stroke="currentColor" class="w-4 h-4"> <path stroke-linecap="round" stroke-linejoin="round" d="M18.75 19.5l-7.5-7.5 7.5-7.5m-6 15L5.25 12l7.5-7.5" @@ -662,7 +662,7 @@

    Via JavaScript

    class="border-r px-6 py-4 dark:border-neutral-500 max-lg:whitespace-nowrap"> <svg xmlns="http://www.w3.org/2000/svg" - fill="currentColor" viewBox="0 0 24 24" stroke-width="2" + fill="currentColor" viewBox="0 0 24 24" stroke-width="3" stroke="currentColor"> <path stroke-linecap="round" stroke-linejoin="round" d="M4.5 10.5L12 3m0 0l7.5 7.5M12 3v18" /> </svg>Via JavaScript
    - py-4 text-clip overflow-hidden + py-4 pl-1 text-clip overflow-hidden text-[#212529] Sets table columns styles. @@ -1369,7 +1369,7 @@

    Via JavaScript

    flex md:flex-row justify-end items-center py-2 space-x-4 - text-sm flex-col + text-sm flex-col leading-[1.6] Sets datatable pagination styles. @@ -1553,7 +1553,7 @@

    Via JavaScript

    - whitespace-nowrap text-clip overflow-hidden px-6 py-4 + whitespace-nowrap text-clip overflow-hidden px-[1.4rem] py-4 Sets row item styles. @@ -1609,7 +1609,7 @@

    Via JavaScript

    - w-20 + w-[70px] Sets select wrapper styles. @@ -1638,9 +1638,9 @@

    Via JavaScript

    - w-5 h-5 pb-1 mr-1 opacity-0 text-neutral-500 - group-hover:opacity-100 transition hover:ease-in-out - transform ease-linear duration-300 + w-[15px] h-[10px] origin-bottom font-black mr-1 opacity-0 + text-neutral-500 group-hover:opacity-100 transition + hover:ease-in-out transform ease-linear duration-300 motion-reduce:transition-none dark:text-neutral-400 @@ -1700,7 +1700,7 @@

    Via JavaScript

    - border-b font-medium + border-b font-normal px-[1.4rem] Sets table header styles. @@ -1714,7 +1714,7 @@

    Via JavaScript

    - text-left text-sm font-light w-full + text-left text-sm font-light w-full leading-[1.6] Sets table styles. diff --git a/site/content/docs/standard/data/datatables/index-js.html b/site/content/docs/standard/data/datatables/index-js.html index b9e1fdb95..e6a51b094 100644 --- a/site/content/docs/standard/data/datatables/index-js.html +++ b/site/content/docs/standard/data/datatables/index-js.html @@ -619,7 +619,6 @@ colorClass.forEach((className) => { cell.classList.add(className); }); - cell.classList.add("font-medium"); }; const columns = [ diff --git a/site/content/docs/standard/data/datatables/index.html b/site/content/docs/standard/data/datatables/index.html index de5307103..fedbb8694 100644 --- a/site/content/docs/standard/data/datatables/index.html +++ b/site/content/docs/standard/data/datatables/index.html @@ -1955,7 +1955,6 @@ colorClass.forEach((className) => { cell.classList.add(className); }); - cell.classList.add("font-medium"); }; const columns = [ @@ -2003,7 +2002,6 @@ colorClass.forEach((className) => { cell.classList.add(className); }); - cell.classList.add("font-medium"); }; const columns = [ diff --git a/src/js/data/datatables/html/columns.js b/src/js/data/datatables/html/columns.js index d35b58b2c..ca4088ef3 100644 --- a/src/js/data/datatables/html/columns.js +++ b/src/js/data/datatables/html/columns.js @@ -48,7 +48,7 @@ const columns = ( column.field }" ${ATTR_SORT_ICON}>${sortIconTemplate}` : "" - } ${ + } ${ column.label }`; }); diff --git a/src/js/data/datatables/html/pagination.js b/src/js/data/datatables/html/pagination.js index 62e335ef6..e2766218c 100644 --- a/src/js/data/datatables/html/pagination.js +++ b/src/js/data/datatables/html/pagination.js @@ -61,24 +61,24 @@ const pagination = (
    ${ fullPagination - ? `` : "" } - - ${ fullPagination - ? `` : "" diff --git a/src/js/data/datatables/html/rows.js b/src/js/data/datatables/html/rows.js index eb28c1afa..ae372e27d 100644 --- a/src/js/data/datatables/html/rows.js +++ b/src/js/data/datatables/html/rows.js @@ -27,7 +27,6 @@ const rows = ({ class="${classes.checkboxRow}" type="checkbox" value="" - id="checkboxDefault" data-te-row-index="${row.rowIndex}" ${ATTR_ROW_CHECKBOX}/>
    py-4 pl-1 text-clip overflow-hidden text-[#212529] + dark:text-white Sets table columns styles. diff --git a/src/js/data/chart/chartDefaults.js b/src/js/data/chart/chartDefaults.js index d6214b3dc..1b09e5742 100644 --- a/src/js/data/chart/chartDefaults.js +++ b/src/js/data/chart/chartDefaults.js @@ -1,3 +1,14 @@ +/* +-------------------------------------------------------------------------- +Tailwind Elements is an open-source UI kit of advanced components for TailwindCSS. +Copyright © 2023 MDBootstrap.com + +Unless a custom, individually assigned license has been granted, this program is free software: you can redistribute it and/or modify it under the terms of the GNU Affero General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. +In addition, a custom license may be available upon request, subject to the terms and conditions of that license. Please contact tailwind@mdbootstrap.com for more information on obtaining a custom license. +This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Affero General Public License for more details. +-------------------------------------------------------------------------- +*/ + // Default options const DEFAULT_LEGEND_COLOR = { plugins: { diff --git a/src/js/data/chart/charts.js b/src/js/data/chart/charts.js index bd47580b6..cd37104a3 100644 --- a/src/js/data/chart/charts.js +++ b/src/js/data/chart/charts.js @@ -1,3 +1,14 @@ +/* +-------------------------------------------------------------------------- +Tailwind Elements is an open-source UI kit of advanced components for TailwindCSS. +Copyright © 2023 MDBootstrap.com + +Unless a custom, individually assigned license has been granted, this program is free software: you can redistribute it and/or modify it under the terms of the GNU Affero General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. +In addition, a custom license may be available upon request, subject to the terms and conditions of that license. Please contact tailwind@mdbootstrap.com for more information on obtaining a custom license. +This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Affero General Public License for more details. +-------------------------------------------------------------------------- +*/ + import { element, typeCheckConfig } from "../../util/index"; import Data from "../../dom/data"; import Manipulator from "../../dom/manipulator"; diff --git a/src/js/data/datatables/html/columns.js b/src/js/data/datatables/html/columns.js index ca4088ef3..973d21945 100644 --- a/src/js/data/datatables/html/columns.js +++ b/src/js/data/datatables/html/columns.js @@ -1,3 +1,14 @@ +/* +-------------------------------------------------------------------------- +Tailwind Elements is an open-source UI kit of advanced components for TailwindCSS. +Copyright © 2023 MDBootstrap.com + +Unless a custom, individually assigned license has been granted, this program is free software: you can redistribute it and/or modify it under the terms of the GNU Affero General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. +In addition, a custom license may be available upon request, subject to the terms and conditions of that license. Please contact tailwind@mdbootstrap.com for more information on obtaining a custom license. +This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Affero General Public License for more details. +-------------------------------------------------------------------------- +*/ + /* eslint-disable indent */ const ATTR_SORT_ICON = "data-te-datatable-sort-icon-ref"; const ATTR_HEADER_CHECKBOX = "data-te-datatable-header-checkbox-ref"; diff --git a/src/js/data/datatables/html/pagination.js b/src/js/data/datatables/html/pagination.js index e2766218c..eab51edc4 100644 --- a/src/js/data/datatables/html/pagination.js +++ b/src/js/data/datatables/html/pagination.js @@ -1,3 +1,14 @@ +/* +-------------------------------------------------------------------------- +Tailwind Elements is an open-source UI kit of advanced components for TailwindCSS. +Copyright © 2023 MDBootstrap.com + +Unless a custom, individually assigned license has been granted, this program is free software: you can redistribute it and/or modify it under the terms of the GNU Affero General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. +In addition, a custom license may be available upon request, subject to the terms and conditions of that license. Please contact tailwind@mdbootstrap.com for more information on obtaining a custom license. +This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Affero General Public License for more details. +-------------------------------------------------------------------------- +*/ + /* eslint-disable indent */ const ATTR_SELECT = "data-te-datatable-select-ref"; const ATTR_PAGINATION_NAV = "data-te-datatable-pagination-nav-ref"; diff --git a/src/js/data/datatables/html/rows.js b/src/js/data/datatables/html/rows.js index ae372e27d..a6e04fa53 100644 --- a/src/js/data/datatables/html/rows.js +++ b/src/js/data/datatables/html/rows.js @@ -1,3 +1,14 @@ +/* +-------------------------------------------------------------------------- +Tailwind Elements is an open-source UI kit of advanced components for TailwindCSS. +Copyright © 2023 MDBootstrap.com + +Unless a custom, individually assigned license has been granted, this program is free software: you can redistribute it and/or modify it under the terms of the GNU Affero General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. +In addition, a custom license may be available upon request, subject to the terms and conditions of that license. Please contact tailwind@mdbootstrap.com for more information on obtaining a custom license. +This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Affero General Public License for more details. +-------------------------------------------------------------------------- +*/ + /* eslint-disable indent */ const ATTR_ROW = "data-te-datatable-row-ref"; const ATTR_ROW_CHECKBOX = "data-te-datatable-row-checkbox-ref"; diff --git a/src/js/data/datatables/html/table.js b/src/js/data/datatables/html/table.js index 3c8fc7c63..a399cdfbe 100644 --- a/src/js/data/datatables/html/table.js +++ b/src/js/data/datatables/html/table.js @@ -1,3 +1,14 @@ +/* +-------------------------------------------------------------------------- +Tailwind Elements is an open-source UI kit of advanced components for TailwindCSS. +Copyright © 2023 MDBootstrap.com + +Unless a custom, individually assigned license has been granted, this program is free software: you can redistribute it and/or modify it under the terms of the GNU Affero General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. +In addition, a custom license may be available upon request, subject to the terms and conditions of that license. Please contact tailwind@mdbootstrap.com for more information on obtaining a custom license. +This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Affero General Public License for more details. +-------------------------------------------------------------------------- +*/ + /* eslint-disable indent */ import paginationTemplate from "./pagination"; import generateColumns from "./columns"; diff --git a/src/js/data/datatables/index.js b/src/js/data/datatables/index.js index 23279c4a6..4569b9ec7 100644 --- a/src/js/data/datatables/index.js +++ b/src/js/data/datatables/index.js @@ -76,7 +76,8 @@ const CHECKBOX_ROW_CLASSES = const CHECKBOX_ROW_WRAPPER_CLASSES = "mb-[0.125rem] min-h-[1.5rem] pl-[1.5rem] ml-3 flex items-center"; const COLOR_CLASSES = "bg-white dark:bg-neutral-800"; -const COLUMNS_CLASSES = "py-4 pl-1 text-clip overflow-hidden text-[#212529]"; +const COLUMNS_CLASSES = + "py-4 pl-1 text-clip overflow-hidden text-[#212529] dark:text-white"; const EDIT_CLASSES = "focus:outline-none"; const FIXED_HEADER_CLASSES = "sticky top-0 z-30"; const FIXED_HEADER_BODY_CLASSES = "sticky z-10 bg-inherit"; diff --git a/src/js/data/datatables/util.js b/src/js/data/datatables/util.js index 43365742d..744c3cd7e 100644 --- a/src/js/data/datatables/util.js +++ b/src/js/data/datatables/util.js @@ -1,3 +1,14 @@ +/* +-------------------------------------------------------------------------- +Tailwind Elements is an open-source UI kit of advanced components for TailwindCSS. +Copyright © 2023 MDBootstrap.com + +Unless a custom, individually assigned license has been granted, this program is free software: you can redistribute it and/or modify it under the terms of the GNU Affero General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. +In addition, a custom license may be available upon request, subject to the terms and conditions of that license. Please contact tailwind@mdbootstrap.com for more information on obtaining a custom license. +This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Affero General Public License for more details. +-------------------------------------------------------------------------- +*/ + const sort = ({ rows, field, order }) => { const sorted = rows.sort((a, b) => { let fieldA = a[field];