playbook_ui 14.6.0.pre.rc.19 → 14.6.0.pre.rc.21

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 3c57569080824d795c74490f22272d41f29f12f0078a175cceeb677080f9fa05
4
- data.tar.gz: b4b34142a01879bb1b2b41b4e505155d4c61f2ad76e2fba571fda9d3fe288471
3
+ metadata.gz: e05fd264b4977a51ad94911511cf1a10fc062530a46ecd437bfa0c8fe977099b
4
+ data.tar.gz: 1099dd1c29b4f7fe79c5a1bec488036fea5bae872ef5fb83c1cd4ff820319a4e
5
5
  SHA512:
6
- metadata.gz: 87c2f61d9de0f934b5d73f676551b78807d9803fa4fad2a55325b7b84737a703f5fa2ff3440423b3588f727e0953e5919e503d77d865cbc442770338d99ab8c6
7
- data.tar.gz: 99ec93ece3e61ade515d6c49d8ad14a25441f6512ddcfee3aa3382a35b460a593c268dec478f333d55fa2a4ec5b767cd6c1ba57f382d3e49d5bd8fd5da1b8631
6
+ metadata.gz: ab871f97c735e0ca94c973a098e6ab1a0d16a4e1bb449c450744a6de0a95c02d0daec4ce1a70581e26114193102522c479cca8253c306dbd2d84434b93f92a2b
7
+ data.tar.gz: 5e96fc933c9e981dc64f42b2b274eed0660c684cbd7130fbdad00cd7e643352de15de4d19ed3045ba8ea4fbff93c20c953f62636b8f384f719d123a0f7edaa34
@@ -91,7 +91,7 @@ const AdvancedTable = (props: AdvancedTableProps) => {
91
91
  const columnHelper = createColumnHelper()
92
92
 
93
93
  //Create cells for first columns
94
- const createCellFunction = (cellAccessors: string[]) => {
94
+ const createCellFunction = (cellAccessors: string[], customRenderer?: (row: Row<GenericObject>, value: any) => JSX.Element) => {
95
95
  const columnCells = ({
96
96
  row,
97
97
  getValue,
@@ -101,6 +101,11 @@ const AdvancedTable = (props: AdvancedTableProps) => {
101
101
  }) => {
102
102
  const rowData = row.original
103
103
 
104
+ // Use customRenderer if provided, otherwise default rendering
105
+ if (customRenderer) {
106
+ return customRenderer(row, getValue())
107
+ }
108
+
104
109
  switch (row.depth) {
105
110
  case 0: {
106
111
  return (
@@ -134,18 +139,31 @@ const AdvancedTable = (props: AdvancedTableProps) => {
134
139
  //Create column array in format needed by Tanstack
135
140
  const columns =
136
141
  columnDefinitions &&
137
- columnDefinitions.map((column) => {
142
+ columnDefinitions.map((column, index) => {
138
143
  // Define the base column structure
139
144
  const columnStructure = {
140
145
  ...columnHelper.accessor(column.accessor, {
141
146
  header: column.label,
142
147
  }),
143
148
  }
144
- if (column.cellAccessors) {
145
- columnStructure.cell = createCellFunction(column.cellAccessors)
146
- }
147
- return columnStructure
148
- })
149
+
150
+ // Use the custom renderer if provided, EXCEPT for the first column
151
+ if (index !== 0) {
152
+ if (column.cellAccessors || column.customRenderer) {
153
+ columnStructure.cell = createCellFunction(
154
+ column.cellAccessors,
155
+ column.customRenderer
156
+ )
157
+ }
158
+ } else {
159
+ // For the first column, apply createCellFunction without customRenderer
160
+ if (column.cellAccessors) {
161
+ columnStructure.cell = createCellFunction(column.cellAccessors)
162
+ }
163
+ }
164
+
165
+ return columnStructure
166
+ })
149
167
 
150
168
  //Syntax for sorting Array if we want to manage state ourselves
151
169
  const sorting = [
@@ -0,0 +1,72 @@
1
+ import React from "react"
2
+ import { AdvancedTable, Pill, Body, Flex, Detail, Caption } from "playbook-ui"
3
+ import MOCK_DATA from "./advanced_table_mock_data.json"
4
+
5
+ const AdvancedTableCustomCell = (props) => {
6
+ const columnDefinitions = [
7
+ {
8
+ accessor: "year",
9
+ label: "Year",
10
+ cellAccessors: ["quarter", "month", "day"],
11
+
12
+ },
13
+ {
14
+ accessor: "newEnrollments",
15
+ label: "New Enrollments",
16
+ customRenderer: (row, value) => (
17
+ <Pill text={value}
18
+ variant="success"
19
+ />
20
+ ),
21
+ },
22
+ {
23
+ accessor: "scheduledMeetings",
24
+ label: "Scheduled Meetings",
25
+ customRenderer: (row, value) => <Body><a href="#">{value}</a></Body>,
26
+ },
27
+ {
28
+ accessor: "attendanceRate",
29
+ label: "Attendance Rate",
30
+ customRenderer: (row, value) => (
31
+ <Flex alignItems="end"
32
+ orientation="column"
33
+ >
34
+ <Detail bold
35
+ color="default"
36
+ text={value}
37
+ />
38
+ <Caption size="xs">{row.original.graduatedStudents}</Caption>
39
+ </Flex>
40
+ ),
41
+ },
42
+ {
43
+ accessor: "completedClasses",
44
+ label: "Completed Classes",
45
+ },
46
+ {
47
+ accessor: "classCompletionRate",
48
+ label: "Class Completion Rate",
49
+ },
50
+ {
51
+ accessor: "graduatedStudents",
52
+ label: "Graduated Students",
53
+ },
54
+ ]
55
+
56
+ return (
57
+ <div>
58
+ <AdvancedTable
59
+ columnDefinitions={columnDefinitions}
60
+ enableToggleExpansion="all"
61
+ responsive="none"
62
+ tableData={MOCK_DATA}
63
+ {...props}
64
+ >
65
+ <AdvancedTable.Header enableSorting />
66
+ <AdvancedTable.Body />
67
+ </AdvancedTable>
68
+ </div>
69
+ )
70
+ }
71
+
72
+ export default AdvancedTableCustomCell
@@ -0,0 +1,5 @@
1
+ The Advanced Table also allows for rendering custom components within individual Cells. To achieve this, you can make use of the optional `customRenderer` item within each columnDefinition. This function gives you access to the current Cell's value if you just want to use that with a custom Kit, but it also gives you access to the entire `row` object. The row object provides all data for the current row. To access the data, use `row.original` which is the entire data object for the current row. See the code snippet below for 3 separate use cases and how they were acheived.
2
+
3
+ See [here](https://playbook.powerapp.cloud/kits/advanced_table/react#columnDefinitions) for more indepth information on columnDefinitions are how to use them.
4
+
5
+ See [here](https://github.com/powerhome/playbook/tree/master/playbook/app/pb_kits/playbook/pb_advanced_table#readme) for the structure of the tableData used.
@@ -3,6 +3,7 @@ examples:
3
3
  - advanced_table_beta: Default (Required Props)
4
4
  - advanced_table_beta_subrow_headers: SubRow Headers
5
5
  - advanced_table_beta_sort: Enable Sorting
6
+
6
7
  react:
7
8
  - advanced_table_default: Default (Required Props)
8
9
  - advanced_table_loading: Loading State
@@ -15,3 +16,4 @@ examples:
15
16
  - advanced_table_table_props: Table Props
16
17
  - advanced_table_inline_row_loading: Inline Row Loading
17
18
  - advanced_table_responsive: Responsive Tables
19
+ - advanced_table_custom_cell: Custom Components for Cells
@@ -9,3 +9,4 @@ export { default as AdvancedTableTableOptions } from './_advanced_table_table_op
9
9
  export { default as AdvancedTableTableProps } from './_advanced_table_table_props.jsx'
10
10
  export { default as AdvancedTableInlineRowLoading } from './_advanced_table_inline_row_loading.jsx'
11
11
  export { default as AdvancedTableResponsive } from './_advanced_table_responsive.jsx'
12
+ export { default as AdvancedTableCustomCell } from './_advanced_table_custom_cell.jsx'
@@ -1,13 +1,36 @@
1
1
  <%= pb_rails("button", props: { text: "Open Dialog", data: {"open-dialog": "dialog-loading"} }) %>
2
2
 
3
- <%= pb_rails("dialog", props: {
4
- id:"dialog-loading",
5
- size: "sm",
6
- title: "Loading Exmaple",
7
- text: "Make a loading request?",
8
- cancel_button: "Cancel Button",
3
+ <%= pb_rails("dialog", props: {
4
+ id:"dialog-loading",
5
+ size: "sm",
6
+ title: "Loading Example",
7
+ text: "Make a loading request?",
8
+ cancel_button: "Cancel Button",
9
9
  cancel_button_id: "cancel-button-loading",
10
- confirm_button: "Okay",
10
+ confirm_button: "Okay",
11
11
  confirm_button_id: "confirm-button-loading",
12
12
  loading: true,
13
13
  }) %>
14
+
15
+ <script>
16
+ const loadingButton = document.querySelector('[data-disable-with="Loading"]');
17
+ if (loadingButton) {
18
+ loadingButton.addEventListener("click", function() {
19
+ const okayLoadingButton = document.querySelector('[data-disable-with="Loading"]');
20
+ const cancelButton = document.querySelector('[data-disable-cancel-with="Loading"]');
21
+ let currentClass = okayLoadingButton.className;
22
+ let cancelClass = cancelButton ? cancelButton.className : "";
23
+
24
+ setTimeout(function() {
25
+ okayLoadingButton.disabled = false;
26
+ okayLoadingButton.className = currentClass.replace("_disabled_loading", "_enabled");
27
+
28
+ if (cancelButton) {
29
+ cancelButton.disabled = false;
30
+ cancelButton.className = cancelClass.replace("_disabled", "_enabled");
31
+ }
32
+ }, 5000);
33
+
34
+ });
35
+ }
36
+ </script>
@@ -1,3 +1 @@
1
1
  Pressing the "Okay" button will trigger a loading state where the button content is replaced by a spinner icon and both buttons are disabled.
2
-
3
- Currently, the loading state cannot be undone and will require a page refresh to reset the dialog.
@@ -0,0 +1,39 @@
1
+ <%= pb_form_with(scope: :example, url: "", method: :get, loading: true) do |form| %>
2
+ <%= form.text_field :example_text_field, props: { label: true } %>
3
+
4
+ <%= form.actions do |action| %>
5
+ <%= action.submit %>
6
+ <%= action.button props: { type: "reset", text: "Cancel", variant: "secondary" } %>
7
+ <% end %>
8
+ <% end %>
9
+
10
+ <script>
11
+ const loadingForm = document.querySelector(".pb_form_loading")
12
+ if (loadingForm) {
13
+ loadingForm.addEventListener("submit", function(event) {
14
+ event.preventDefault();
15
+
16
+ const submitButton = event['submitter'];
17
+ const cancelButton = event['target'].querySelector('button[type="reset"]');
18
+
19
+ if (submitButton) {
20
+ let currentClass = submitButton.className;
21
+ let newClass = currentClass.replace("_disabled_loading", "_enabled");
22
+
23
+ let cancelClass = cancelButton ? cancelButton.className : "";
24
+ let newCancelClass = cancelClass.replace("_disabled", "_enabled");
25
+
26
+ setTimeout(function() {
27
+ submitButton.disabled = false;
28
+ submitButton.className = currentClass;
29
+
30
+ if (cancelButton) {
31
+ cancelButton.disabled = false;
32
+ cancelButton.className = cancelClass;
33
+ }
34
+ }, 5000);
35
+ }
36
+ });
37
+ }
38
+ </script>
39
+
@@ -0,0 +1 @@
1
+ Pressing Submit will trigger a loading state where the button content is replaced by a spinner icon and the submit button will be disabled.
@@ -3,3 +3,4 @@ examples:
3
3
  rails:
4
4
  - form_form_with: Default
5
5
  - form_form_with_validate: Default + Validation
6
+ - form_form_with_loading: Default + Loading
@@ -7,6 +7,7 @@ module Playbook
7
7
  type: Playbook::Props::Base
8
8
  prop :form_system_options, deprecated: "Use options instead",
9
9
  type: Playbook::Props::Base
10
+ prop :loading, type: Playbook::Props::Boolean, default: false
10
11
  prop :options, type: Playbook::Props::Base
11
12
  prop :validate, type: Playbook::Props::Boolean, default: false
12
13
 
@@ -22,6 +23,7 @@ module Playbook
22
23
  aria: aria,
23
24
  class: classname,
24
25
  data: data,
26
+ loading: loading,
25
27
  validate: validate,
26
28
  }.merge(prop(:options) || prop(:form_system_options) || {})
27
29
  end
@@ -0,0 +1,27 @@
1
+ const formHelper = () => {
2
+ const loadingForm = document.querySelector(".pb_form_loading")
3
+ if (loadingForm) {
4
+ loadingForm.addEventListener("submit", function(event) {
5
+ const submitButton = event['submitter'];
6
+ const cancelButton = event['target'].querySelector('button[type="reset"]');
7
+
8
+ if (submitButton) {
9
+ let currentClass = submitButton.className;
10
+ let newClass = currentClass.replace("_enabled", "_disabled_loading");
11
+
12
+ let cancelClass = cancelButton ? cancelButton.className : "";
13
+ let newCancelClass = cancelClass.replace("_enabled", "_disabled");
14
+
15
+ submitButton.disabled = true;
16
+ submitButton.className = newClass;
17
+
18
+ if (cancelButton) {
19
+ cancelButton.disabled = true;
20
+ cancelButton.className = newCancelClass;
21
+ }
22
+ }
23
+ });
24
+ }
25
+ };
26
+
27
+ export default formHelper;
@@ -1,4 +1,4 @@
1
- import{jsx as jsx$1,Fragment,jsxs}from"react/jsx-runtime";import*as React from"react";import React__default,{createContext,useReducer,useEffect,useMemo,useContext,createElement,useState,useRef,forwardRef,useCallback,useImperativeHandle,useLayoutEffect,Component,Fragment as Fragment$1}from"react";import{n as getDefaultExportFromCjs,v as filter,w as omit,i as getAllIcons,x as get,l as commonjsGlobal,t as colors$1,r as highchartsTheme,y as merge,q as highchartsDarkTheme,z as useCollapsible,A as getAugmentedNamespace,B as createPopper,C as uniqueId,E as typography,F as cloneDeep,G as isString}from"./lib-CEpcaI8y.js";import*as ReactDOM from"react-dom";import ReactDOM__default,{createPortal}from"react-dom";import{TrixEditor}from"react-trix";import Trix from"trix";import require$$0 from"react-is";const initialState={items:[],dragData:{id:"",initialGroup:""},isDragging:"",activeContainer:""};const reducer=(state,action)=>{switch(action.type){case"SET_ITEMS":return Object.assign(Object.assign({},state),{items:action.payload});case"SET_DRAG_DATA":return Object.assign(Object.assign({},state),{dragData:action.payload});case"SET_IS_DRAGGING":return Object.assign(Object.assign({},state),{isDragging:action.payload});case"SET_ACTIVE_CONTAINER":return Object.assign(Object.assign({},state),{activeContainer:action.payload});case"CHANGE_CATEGORY":return Object.assign(Object.assign({},state),{items:state.items.map((item=>item.id===action.payload.itemId?Object.assign(Object.assign({},item),{container:action.payload.container}):item))});case"REORDER_ITEMS":{const{dragId:dragId,targetId:targetId}=action.payload;const newItems=[...state.items];const draggedItem=newItems.find((item=>item.id===dragId));const draggedIndex=newItems.indexOf(draggedItem);const targetIndex=newItems.findIndex((item=>item.id===targetId));newItems.splice(draggedIndex,1);newItems.splice(targetIndex,0,draggedItem);return Object.assign(Object.assign({},state),{items:newItems})}default:return state}};const DragContext=createContext({});const DraggableContext=()=>useContext(DragContext);const DraggableProvider=({children:children,initialItems:initialItems,onReorder:onReorder,onDragStart:onDragStart,onDragEnter:onDragEnter,onDragEnd:onDragEnd,onDrop:onDrop,onDragOver:onDragOver})=>{const[state,dispatch]=useReducer(reducer,initialState);useEffect((()=>{dispatch({type:"SET_ITEMS",payload:initialItems})}),[initialItems]);useEffect((()=>{onReorder(state.items)}),[state.items]);const handleDragStart=(id,container)=>{dispatch({type:"SET_DRAG_DATA",payload:{id:id,initialGroup:container}});dispatch({type:"SET_IS_DRAGGING",payload:id});if(onDragStart)onDragStart(id,container)};const handleDragEnter=(id,container)=>{if(state.dragData.id!==id){dispatch({type:"REORDER_ITEMS",payload:{dragId:state.dragData.id,targetId:id}});dispatch({type:"SET_DRAG_DATA",payload:{id:state.dragData.id,initialGroup:container}})}if(onDragEnter)onDragEnter(id,container)};const handleDragEnd=()=>{dispatch({type:"SET_IS_DRAGGING",payload:""});dispatch({type:"SET_ACTIVE_CONTAINER",payload:""});if(onDragEnd)onDragEnd()};const changeCategory=(itemId,container)=>{dispatch({type:"CHANGE_CATEGORY",payload:{itemId:itemId,container:container}})};const handleDrop=container=>{dispatch({type:"SET_IS_DRAGGING",payload:""});dispatch({type:"SET_ACTIVE_CONTAINER",payload:""});changeCategory(state.dragData.id,container);if(onDrop)onDrop(container)};const handleDragOver=(e2,container)=>{e2.preventDefault();dispatch({type:"SET_ACTIVE_CONTAINER",payload:container});if(onDragOver)onDragOver(e2,container)};const contextValue=useMemo((()=>({items:state.items,dragData:state.dragData,isDragging:state.isDragging,activeContainer:state.activeContainer,handleDragStart:handleDragStart,handleDragEnter:handleDragEnter,handleDragEnd:handleDragEnd,handleDrop:handleDrop,handleDragOver:handleDragOver})),[state]);return jsx$1(DragContext.Provider,Object.assign({value:contextValue},{children:children}),void 0)};var classnames$1={exports:{}};
1
+ import{jsx as jsx$1,Fragment,jsxs}from"react/jsx-runtime";import*as React from"react";import React__default,{createContext,useReducer,useEffect,useMemo,useContext,createElement,useState,useRef,forwardRef,useCallback,useImperativeHandle,useLayoutEffect,Component,Fragment as Fragment$1}from"react";import{q as getDefaultExportFromCjs,w as filter,x as omit,j as getAllIcons,y as get,n as commonjsGlobal,v as colors$1,s as highchartsTheme,z as merge,r as highchartsDarkTheme,A as useCollapsible,B as getAugmentedNamespace,C as createPopper,E as uniqueId,F as typography,G as cloneDeep,H as isString}from"./lib-D-mTv-kp.js";import*as ReactDOM from"react-dom";import ReactDOM__default,{createPortal}from"react-dom";import{TrixEditor}from"react-trix";import Trix from"trix";import require$$0 from"react-is";const initialState={items:[],dragData:{id:"",initialGroup:""},isDragging:"",activeContainer:""};const reducer=(state,action)=>{switch(action.type){case"SET_ITEMS":return Object.assign(Object.assign({},state),{items:action.payload});case"SET_DRAG_DATA":return Object.assign(Object.assign({},state),{dragData:action.payload});case"SET_IS_DRAGGING":return Object.assign(Object.assign({},state),{isDragging:action.payload});case"SET_ACTIVE_CONTAINER":return Object.assign(Object.assign({},state),{activeContainer:action.payload});case"CHANGE_CATEGORY":return Object.assign(Object.assign({},state),{items:state.items.map((item=>item.id===action.payload.itemId?Object.assign(Object.assign({},item),{container:action.payload.container}):item))});case"REORDER_ITEMS":{const{dragId:dragId,targetId:targetId}=action.payload;const newItems=[...state.items];const draggedItem=newItems.find((item=>item.id===dragId));const draggedIndex=newItems.indexOf(draggedItem);const targetIndex=newItems.findIndex((item=>item.id===targetId));newItems.splice(draggedIndex,1);newItems.splice(targetIndex,0,draggedItem);return Object.assign(Object.assign({},state),{items:newItems})}default:return state}};const DragContext=createContext({});const DraggableContext=()=>useContext(DragContext);const DraggableProvider=({children:children,initialItems:initialItems,onReorder:onReorder,onDragStart:onDragStart,onDragEnter:onDragEnter,onDragEnd:onDragEnd,onDrop:onDrop,onDragOver:onDragOver})=>{const[state,dispatch]=useReducer(reducer,initialState);useEffect((()=>{dispatch({type:"SET_ITEMS",payload:initialItems})}),[initialItems]);useEffect((()=>{onReorder(state.items)}),[state.items]);const handleDragStart=(id,container)=>{dispatch({type:"SET_DRAG_DATA",payload:{id:id,initialGroup:container}});dispatch({type:"SET_IS_DRAGGING",payload:id});if(onDragStart)onDragStart(id,container)};const handleDragEnter=(id,container)=>{if(state.dragData.id!==id){dispatch({type:"REORDER_ITEMS",payload:{dragId:state.dragData.id,targetId:id}});dispatch({type:"SET_DRAG_DATA",payload:{id:state.dragData.id,initialGroup:container}})}if(onDragEnter)onDragEnter(id,container)};const handleDragEnd=()=>{dispatch({type:"SET_IS_DRAGGING",payload:""});dispatch({type:"SET_ACTIVE_CONTAINER",payload:""});if(onDragEnd)onDragEnd()};const changeCategory=(itemId,container)=>{dispatch({type:"CHANGE_CATEGORY",payload:{itemId:itemId,container:container}})};const handleDrop=container=>{dispatch({type:"SET_IS_DRAGGING",payload:""});dispatch({type:"SET_ACTIVE_CONTAINER",payload:""});changeCategory(state.dragData.id,container);if(onDrop)onDrop(container)};const handleDragOver=(e2,container)=>{e2.preventDefault();dispatch({type:"SET_ACTIVE_CONTAINER",payload:container});if(onDragOver)onDragOver(e2,container)};const contextValue=useMemo((()=>({items:state.items,dragData:state.dragData,isDragging:state.isDragging,activeContainer:state.activeContainer,handleDragStart:handleDragStart,handleDragEnter:handleDragEnter,handleDragEnd:handleDragEnd,handleDrop:handleDrop,handleDragOver:handleDragOver})),[state]);return jsx$1(DragContext.Provider,Object.assign({value:contextValue},{children:children}),void 0)};var classnames$1={exports:{}};
2
2
  /*!
3
3
  Copyright (c) 2018 Jed Watson.
4
4
  Licensed under the MIT License (MIT), see