playbook_ui 12.24.0 → 12.25.0.pre.alpha.PLAY818multilevelrebuild770

Sign up to get free protection for your applications and to get access to all the features.
Files changed (41) hide show
  1. checksums.yaml +4 -4
  2. data/app/pb_kits/playbook/pb_avatar/docs/_avatar_swift.md +82 -1
  3. data/app/pb_kits/playbook/pb_date/_date.tsx +96 -42
  4. data/app/pb_kits/playbook/pb_date/date.html.erb +22 -2
  5. data/app/pb_kits/playbook/pb_date/date.rb +2 -0
  6. data/app/pb_kits/playbook/pb_date/docs/_date_unstyled.html.erb +30 -0
  7. data/app/pb_kits/playbook/pb_date/docs/_date_unstyled.jsx +47 -0
  8. data/app/pb_kits/playbook/pb_date/docs/_date_unstyled.md +1 -0
  9. data/app/pb_kits/playbook/pb_date/docs/example.yml +4 -4
  10. data/app/pb_kits/playbook/pb_date/docs/index.js +1 -0
  11. data/app/pb_kits/playbook/pb_docs/kit_example.html.erb +14 -13
  12. data/app/pb_kits/playbook/pb_docs/kit_example.rb +0 -2
  13. data/app/pb_kits/playbook/pb_form_pill/_form_pill.tsx +3 -2
  14. data/app/pb_kits/playbook/pb_multi_level_select/_helper_functions.tsx +212 -0
  15. data/app/pb_kits/playbook/pb_multi_level_select/_multi_level_select.scss +53 -98
  16. data/app/pb_kits/playbook/pb_multi_level_select/_multi_level_select.tsx +340 -86
  17. data/app/pb_kits/playbook/pb_multi_level_select/docs/_multi_level_select_default.md +1 -1
  18. data/app/pb_kits/playbook/pb_multi_level_select/docs/_multi_level_select_return_all_selected.html.erb +1 -0
  19. data/app/pb_kits/playbook/pb_multi_level_select/multi_level_select.test.jsx +1 -1
  20. data/app/pb_kits/playbook/pb_time/_time.tsx +71 -35
  21. data/app/pb_kits/playbook/pb_time/docs/_time_unstyled.html.erb +37 -0
  22. data/app/pb_kits/playbook/pb_time/docs/_time_unstyled.jsx +58 -0
  23. data/app/pb_kits/playbook/pb_time/docs/_time_unstyled.md +1 -0
  24. data/app/pb_kits/playbook/pb_time/docs/example.yml +2 -0
  25. data/app/pb_kits/playbook/pb_time/docs/index.js +1 -0
  26. data/app/pb_kits/playbook/pb_time/time.html.erb +26 -7
  27. data/app/pb_kits/playbook/pb_time/time.rb +2 -0
  28. data/app/pb_kits/playbook/pb_title/_title.scss +2 -1
  29. data/app/pb_kits/playbook/pb_title/_title.tsx +3 -2
  30. data/app/pb_kits/playbook/pb_title/title.rb +10 -3
  31. data/app/pb_kits/playbook/pb_title/title.test.js +3 -3
  32. data/dist/playbook-rails.js +51 -0
  33. data/lib/playbook/version.rb +2 -2
  34. data/lib/playbook.rb +1 -2
  35. metadata +19 -43
  36. data/app/pb_kits/playbook/pb_docs/kit_api.html.erb +0 -311
  37. data/app/pb_kits/playbook/pb_docs/kit_api.rb +0 -149
  38. data/app/pb_kits/playbook/pb_multi_level_select/_multi_select_helper.tsx +0 -31
  39. data/app/pb_kits/playbook/pb_multi_level_select/helper_functions.ts +0 -87
  40. data/lib/playbook/markdown/helper.rb +0 -132
  41. data/lib/playbook/markdown.rb +0 -3
@@ -1,9 +1,24 @@
1
- import React, { useState, useEffect, useMemo } from "react";
1
+ import React, { useState, useEffect, useRef } from "react";
2
2
  import classnames from "classnames";
3
3
  import { buildAriaProps, buildCss, buildDataProps } from "../utilities/props";
4
- import { globalProps } from "../utilities/globalProps";
5
- import { findItemById, checkIt, unCheckIt, getParentAndAncestorsIds } from "./helper_functions";
6
- import MultiSelectHelper from "./_multi_select_helper";
4
+ import { globalProps, GlobalProps } from "../utilities/globalProps";
5
+ import Icon from "../pb_icon/_icon";
6
+ import Checkbox from "../pb_checkbox/_checkbox";
7
+ import FormPill from "../pb_form_pill/_form_pill";
8
+ import CircleIconButton from "../pb_circle_icon_button/_circle_icon_button";
9
+ import {
10
+ unCheckIt,
11
+ getAncestorsOfUnchecked,
12
+ unCheckedRecursive,
13
+ checkedRecursive,
14
+ filterFormattedDataById,
15
+ findByFilter,
16
+ getCheckedItems,
17
+ updateReturnItems,
18
+ recursiveReturnOnlyParent,
19
+ removeChildrenIfParentChecked,
20
+ getChildIds,
21
+ } from "./_helper_functions";
7
22
 
8
23
  type MultiLevelSelectProps = {
9
24
  aria?: { [key: string]: string };
@@ -13,7 +28,7 @@ type MultiLevelSelectProps = {
13
28
  returnAllSelected?: boolean;
14
29
  treeData?: { [key: string]: string }[];
15
30
  onSelect?: (prop: { [key: string]: any }) => void;
16
- };
31
+ } & GlobalProps;
17
32
 
18
33
  const MultiLevelSelect = (props: MultiLevelSelectProps) => {
19
34
  const {
@@ -34,104 +49,343 @@ const MultiLevelSelect = (props: MultiLevelSelectProps) => {
34
49
  className
35
50
  );
36
51
 
52
+ const dropdownRef = useRef(null);
53
+
54
+ //state for whether dropdown is open or closed
55
+ const [isClosed, setIsClosed] = useState(true);
56
+ //state from onchange for textinput, to use for filtering to create typeahead
57
+ const [filterItem, setFilterItem] = useState("");
58
+ //this is essentially the return that the user will get when they use the kit
59
+ const [returnedArray, setReturnedArray] = useState([]);
60
+ //formattedData with checked and parent_id added
37
61
  const [formattedData, setFormattedData] = useState(treeData);
38
- const [selectedItems, setSelectedItems] = useState([]);
39
- const [checkedData, setCheckedData] = useState([]);
40
-
41
- const onChange = (currentNode: { [key: string]: any }) => {
42
- const updatedData = formattedData.map((item: any) => {
43
- if (item.id === currentNode._id) {
44
- if (currentNode.checked) {
45
- checkIt(item, selectedItems, setSelectedItems, false);
46
- } else {
47
- unCheckIt(item, selectedItems, setSelectedItems, false);
48
- }
49
- } else if (item.children) {
50
- const foundItem = findItemById(item.children, currentNode._id);
51
- if (foundItem) {
52
- if (currentNode.checked) {
53
- checkIt(foundItem, selectedItems, setSelectedItems, false);
54
- if (currentNode._parent) {
55
- const parents = getParentAndAncestorsIds(currentNode._parent, formattedData)
56
- parents.forEach((item:string) => {
57
- const ancestor = findItemById(formattedData,item)
58
- ancestor.expanded = true
59
- });
60
- }
61
- } else {
62
- unCheckIt(foundItem, selectedItems, setSelectedItems, false);
63
- if (currentNode._parent) {
64
- const parents = getParentAndAncestorsIds(currentNode._parent, formattedData)
65
- parents.forEach((item:string) => {
66
- const ancestor = findItemById(formattedData,item)
67
- ancestor.expanded = true
68
- });
69
- }
70
- }
71
- }
62
+ //toggle chevron in dropdown
63
+ //@ts-ignore
64
+ const [isToggled, setIsToggled] = useState<{ [id: number]: boolean }>({});
65
+ //state for return for default
66
+ const [defaultReturn, setDefaultReturn] = useState([]);
67
+
68
+ useEffect(() => {
69
+ let el = document.getElementById(`pb_data_wrapper_${id}`);
70
+ if (el) {
71
+ el.setAttribute(
72
+ "data-tree",
73
+ JSON.stringify(returnAllSelected ? returnedArray : defaultReturn)
74
+ );
75
+ }
76
+ returnAllSelected
77
+ ? onSelect(returnedArray)
78
+ : onSelect(
79
+ defaultReturn.filter(
80
+ (item, index, self) =>
81
+ index === self.findIndex((obj) => obj.id === item.id)
82
+ )
83
+ );
84
+ }, [returnedArray, defaultReturn]);
85
+
86
+ useEffect(() => {
87
+ //Create new formattedData array for use
88
+ setFormattedData(addCheckedAndParentProperty(treeData));
89
+ // Function to handle clicks outside the dropdown
90
+ const handleClickOutside = (event: any) => {
91
+ if (dropdownRef.current && !dropdownRef.current.contains(event.target)) {
92
+ setIsClosed(true);
72
93
  }
94
+ };
95
+ //if any items already checked in first render, set return accordingly
96
+ const initialChecked = getCheckedItems(treeData)
97
+ initialChecked && returnAllSelected && setReturnedArray(initialChecked)
98
+ initialChecked && !returnAllSelected && setDefaultReturn(initialChecked)
73
99
 
74
- return item;
75
- });
100
+ // Attach the event listener
101
+ window.addEventListener("click", handleClickOutside);
102
+ // Clean up the event listener on unmount
103
+ return () => {
104
+ window.removeEventListener("click", handleClickOutside);
105
+ };
106
+ }, []);
76
107
 
77
- setFormattedData(updatedData);
108
+ //function to map over data and add parent_id + depth property to each item
109
+ const addCheckedAndParentProperty = (
110
+ treeData: { [key: string]: any }[],
111
+ parent_id: string = null,
112
+ depth: number = 0,
113
+ ) => {
114
+ if (!Array.isArray(treeData)) {
115
+ return;
116
+ }
117
+ return treeData.map((item: { [key: string]: any } | any) => {
118
+ const newItem = {
119
+ ...item,
120
+ parent_id,
121
+ depth,
122
+ };
123
+ if (newItem.children && newItem.children.length > 0) {
124
+ newItem.children = addCheckedAndParentProperty(
125
+ newItem.children,
126
+ newItem.id,
127
+ depth + 1,
128
+ );
129
+ }
130
+ return newItem;
131
+ });
78
132
  };
79
133
 
80
- useEffect(() => {
134
+ //click event for x on form pill
135
+ const handlePillClose = (event: any, clickedItem: { [key: string]: any }) => {
136
+ // prevents the dropdown from closing when clicking on the pill
137
+ event.stopPropagation();
138
+ //logic for removing items from returnArray or defaultReturn when pills clicked
81
139
  if (returnAllSelected) {
82
- const selected = selectedItems.filter(
83
- (item: { [key: string]: any }) => item.checked
84
- );
85
- //filter to remove duplicate items
86
- const uniqueSelected = selected.filter(
87
- (obj, index, self) => index === self.findIndex((t) => t.id === obj.id)
88
- );
89
- setCheckedData(uniqueSelected);
140
+ if (returnedArray.includes(clickedItem)) {
141
+ if (clickedItem.children && clickedItem.children.length > 0) {
142
+ const childrenOfChecked = getChildIds(clickedItem, returnedArray);
143
+ const updatedFiltered = returnedArray
144
+ .filter((item) => item !== clickedItem)
145
+ .filter((item) => !childrenOfChecked.includes(item.id));
146
+ setReturnedArray(updatedFiltered);
147
+ } else {
148
+ const updatedFiltered = returnedArray.filter(
149
+ (item) => item !== clickedItem
150
+ );
151
+ setReturnedArray(updatedFiltered);
152
+ }
153
+ }
154
+ } else {
155
+ if (defaultReturn.includes(clickedItem)) {
156
+ getAncestorsOfUnchecked(formattedData, clickedItem);
157
+ const newChecked = getCheckedItems(formattedData);
158
+ const filteredReturn = updateReturnItems(newChecked).filter(
159
+ (item) => item.id !== clickedItem.id
160
+ );
161
+ setDefaultReturn(filteredReturn);
162
+ }
163
+ }
164
+ if (clickedItem.children && clickedItem.children.length > 0) {
165
+ unCheckedRecursive(clickedItem);
90
166
  }
91
- }, [selectedItems]);
167
+ //logic to uncheck clickedItem in formattedData
168
+ unCheckIt(formattedData, clickedItem.id);
169
+ };
92
170
 
93
- useEffect(() => {
94
- let el = document.getElementById(`pb_data_wrapper_${id}`);
95
- if (el) {
96
- el.setAttribute("data-tree", JSON.stringify(checkedData));
171
+ //handle click on input wrapper(entire div with pills, typeahead, etc) so it doesn't close when input or form pill is clicked
172
+ const handleInputWrapperClick = (e: any) => {
173
+ e.stopPropagation();
174
+ if (
175
+ e.target.id === "multiselect_input" ||
176
+ e.target.classList.contains("pb_form_pill_tag")
177
+ ) {
178
+ return;
97
179
  }
98
- if (returnAllSelected) {
99
- onSelect(checkedData);
180
+ setIsClosed(!isClosed);
181
+ };
182
+
183
+ //Main function to handle any click inside dropdown
184
+ const handledropdownItemClick = (e: any) => {
185
+ const clickedItem = e.target.parentNode.id;
186
+ //setting filterItem to "" will clear textinput and clear typeahead
187
+ setFilterItem("");
188
+
189
+ const filtered = filterFormattedDataById(formattedData, clickedItem);
190
+ //check and uncheck all children of checked/unchecked parent item
191
+ if (filtered[0].children && filtered[0].children.length > 0) {
192
+ if (filtered[0].checked) {
193
+ filtered[0].children.forEach((item: { [key: string]: any }) => {
194
+ checkedRecursive(item);
195
+ });
196
+ } else if (!filtered[0].checked) {
197
+ filtered[0].children.forEach((item: { [key: string]: any }) => {
198
+ unCheckedRecursive(item);
199
+ });
200
+ }
201
+ }
202
+
203
+ const checkedItems = getCheckedItems(formattedData);
204
+
205
+ //checking and unchecking items for returnAllSelected variant
206
+ if (returnedArray.includes(filtered[0])) {
207
+ if (!filtered[0].checked) {
208
+ if (filtered[0].children && filtered[0].children.length > 0) {
209
+ const childrenOfChecked = getChildIds(filtered[0], returnedArray);
210
+ const updatedFiltered = returnedArray
211
+ .filter((item) => item !== filtered[0])
212
+ .filter((item) => !childrenOfChecked.includes(item.id));
213
+
214
+ setReturnedArray(updatedFiltered);
215
+ } else {
216
+ const updatedFiltered = returnedArray.filter(
217
+ (item) => item !== filtered[0]
218
+ );
219
+ setReturnedArray(updatedFiltered);
220
+ }
221
+ }
222
+ } else {
223
+ setReturnedArray(checkedItems);
100
224
  }
101
- }, [checkedData]);
102
225
 
103
- const DropDownSelectComponent = useMemo(() => {
226
+ //when item is unchecked for default variant
227
+ if (!filtered[0].checked && !returnAllSelected) {
228
+ //uncheck parent and grandparent if any child unchecked
229
+ getAncestorsOfUnchecked(formattedData, filtered[0]);
230
+
231
+ const newChecked = getCheckedItems(formattedData);
232
+ //get all checked items, and filter to check if all children checked, if yes return only parent
233
+ const filteredReturn = updateReturnItems(newChecked);
234
+ setDefaultReturn(filteredReturn);
235
+ }
236
+
237
+ //when item is checked for default variant
238
+ if (!returnAllSelected && filtered[0].checked) {
239
+ //if checked item has children
240
+ if (filtered[0].children && filtered[0].children.length > 0) {
241
+ removeChildrenIfParentChecked(
242
+ filtered[0],
243
+ defaultReturn,
244
+ setDefaultReturn
245
+ );
246
+ }
247
+
248
+ //if clicked item has parent_id, find parent and check if all children checked or not
249
+ if (filtered[0].parent_id !== null) {
250
+ recursiveReturnOnlyParent(
251
+ filtered[0],
252
+ formattedData,
253
+ defaultReturn,
254
+ setDefaultReturn
255
+ );
256
+ } else {
257
+ setDefaultReturn([filtered[0]]);
258
+ }
259
+ }
260
+ };
261
+
262
+ //handle click on chevron toggles in dropdown
263
+ const handleToggleClick = (id: string, event: React.MouseEvent) => {
264
+ event.stopPropagation();
265
+ setIsToggled((prevState: { [id: string]: boolean }) => ({
266
+ ...prevState,
267
+ [id]: !prevState[id],
268
+ }));
269
+ const clickedItem = filterFormattedDataById(formattedData, id);
270
+
271
+ if (clickedItem) {
272
+ clickedItem[0].expanded = !clickedItem[0].expanded;
273
+ }
274
+ };
275
+
276
+ //rendering formattedData to UI based on typeahead
277
+ const renderNestedOptions = (items: { [key: string]: any }[]) => {
104
278
  return (
105
- <MultiSelectHelper
106
- treeData={formattedData}
107
- onChange={(
108
- // @ts-ignore
109
- selectedNodes: { [key: string]: any }[],
110
- currentNode: { [key: string]: any }[]
111
- ) => {
112
- setCheckedData(currentNode);
113
- onSelect(currentNode);
114
-
115
- }}
116
- id={id}
117
- {...props}
118
- />
279
+ <ul>
280
+ {Array.isArray(items) &&
281
+ items.map((item: { [key: string]: any }) => {
282
+ return (
283
+ <>
284
+ <li
285
+ key={item.id}
286
+ className="dropdown_item"
287
+ data-name={item.id}
288
+ >
289
+ <div className="dropdown_item_checkbox_row">
290
+ <div
291
+ key={
292
+ item.expanded ? "chevron-down" : "chevron-right"
293
+ }
294
+ >
295
+ <CircleIconButton
296
+ icon={
297
+ item.expanded ? "chevron-down" : "chevron-right"
298
+ }
299
+ className={item.children && !filterItem ? "" : "toggle_icon"}
300
+ onClick={(event) => handleToggleClick(item.id, event)}
301
+ variant="link"
302
+ />
303
+ </div>
304
+ <Checkbox text={item.label} id={item.id}>
305
+ <input
306
+ checked={item.checked}
307
+ type="checkbox"
308
+ name={item.label}
309
+ value={item.label}
310
+ onChange={(e) => {
311
+ item.checked = !item.checked;
312
+ handledropdownItemClick(e);
313
+ }}
314
+ />
315
+ </Checkbox>
316
+ </div>
317
+ {item.expanded &&
318
+ item.children &&
319
+ item.children.length > 0 &&
320
+ !filterItem && ( // Show children if expanded is true
321
+ <div>{renderNestedOptions(item.children)}</div>
322
+ )}
323
+ </li>
324
+ </>
325
+ );
326
+ })}
327
+ </ul>
119
328
  );
120
- }, [formattedData])
329
+ };
121
330
 
122
331
  return (
123
332
  <div {...ariaProps} {...dataProps} className={classes} id={id}>
124
- {returnAllSelected ? (
125
- <MultiSelectHelper
126
- treeData={formattedData}
127
- treeMode={returnAllSelected}
128
- id={id}
129
- onChange={onChange}
130
- {...props}
131
- />
132
- ) : (
133
- <>{DropDownSelectComponent}</>
134
- )}
333
+ <div ref={dropdownRef} className="wrapper">
334
+ <div className="input_wrapper" onClick={handleInputWrapperClick}>
335
+ <div className="input_inner_container">
336
+ {returnedArray.length !== 0 && returnAllSelected
337
+ ? returnedArray.map((item, index) => (
338
+ <FormPill
339
+ key={index}
340
+ text={item.label}
341
+ size="small"
342
+ onClick={(event) => handlePillClose(event, item)}
343
+ />
344
+ ))
345
+ : null}
346
+ {!returnAllSelected &&
347
+ defaultReturn.length !== 0 &&
348
+ defaultReturn
349
+ .filter(
350
+ (item, index, self) =>
351
+ index === self.findIndex((obj) => obj.id === item.id)
352
+ )
353
+ .map((item, index) => (
354
+ <FormPill
355
+ key={index}
356
+ text={item.label}
357
+ size="small"
358
+ onClick={(event) => handlePillClose(event, item)}
359
+ />
360
+ ))}
361
+ {returnedArray.length !== 0 && returnAllSelected && <br />}
362
+ {defaultReturn.length !== 0 && !returnAllSelected && <br />}
363
+ <input
364
+ id="multiselect_input"
365
+ onChange={(e) => {
366
+ setFilterItem(e.target.value);
367
+ }}
368
+ placeholder="Start typing..."
369
+ value={filterItem}
370
+ onClick={() => setIsClosed(false)}
371
+ />
372
+ </div>
373
+ {isClosed ? (
374
+ <div key="chevron-down">
375
+ <Icon icon="chevron-down" />
376
+ </div>
377
+ ) : (
378
+ <div key="chevron-up">
379
+ <Icon icon="chevron-up" />
380
+ </div>
381
+ )}
382
+ </div>
383
+ <div className={`dropdown_menu ${isClosed ? "close" : "open"}`}>
384
+ {renderNestedOptions(
385
+ filterItem ? findByFilter(formattedData, filterItem) : formattedData
386
+ )}
387
+ </div>
388
+ </div>
135
389
  </div>
136
390
  );
137
391
  };
@@ -2,4 +2,4 @@ The MultiLevelSelect kit renders a multi leveled select dropdown based on data f
2
2
 
3
3
  For the React version of the kit, the `onSelect` prop returns an array of all checked items, irrespective of whether it is a parent, child or grandchild. Open the console on this example and check and uncheck checkboxes to see this is action!
4
4
 
5
- For the Rails version, the array of checked items is attached to the DOM in a data attribute titled `data-tree` on the wrapping div around the MultiLevelSelect.
5
+ For the Rails version, the array of checked items is attached to the DOM in a data attribute titled `data-tree` on the wrapping div around the MultiLevelSelect.
@@ -3,6 +3,7 @@
3
3
  value: "Power Home Remodeling",
4
4
  id: "powerhome1",
5
5
  expanded: true,
6
+
6
7
  children: [
7
8
  {
8
9
  label: "People",
@@ -16,7 +16,7 @@ const treeData = {
16
16
  {
17
17
  label: 'No one can get me',
18
18
  value: 'anonymous',
19
- id:'default2',
19
+ id:'default3',
20
20
  },
21
21
  ],
22
22
  },
@@ -20,6 +20,7 @@ type TimeProps = {
20
20
  size?: "md" | "sm";
21
21
  showTimezone?: boolean;
22
22
  timeZone?: string;
23
+ unstyled?: boolean;
23
24
  } & GlobalProps
24
25
 
25
26
  const Time = (props: TimeProps) => {
@@ -30,8 +31,10 @@ const Time = (props: TimeProps) => {
30
31
  showIcon,
31
32
  size,
32
33
  timeZone,
34
+ unstyled = false,
33
35
  showTimezone = true,
34
36
  } = props;
37
+
35
38
  const classes = classnames(
36
39
  buildCss("pb_time_kit", align, size),
37
40
  globalProps(props),
@@ -43,46 +46,79 @@ const Time = (props: TimeProps) => {
43
46
  return (
44
47
  <div className={classes}>
45
48
  {showIcon && (
46
- <>
47
- <Body color="light" tag="span">
48
- <Icon fixedWidth icon="clock" size={size === "md" ? "" : "sm"} />
49
- </Body>{" "}
50
- </>
51
- )}
52
-
53
- <time dateTime={date}>
54
- <span>
55
- {size === "md" ? (
56
- <>
57
- <Body
58
- className="pb_time"
59
- tag="span"
60
- text={dateTimestamp.toTimeWithMeridian()}
61
- />{" "}
62
- {showTimezone && (
63
- <Body
64
- color="light"
65
- tag="span"
66
- text={dateTimestamp.toTimezone()}
49
+ unstyled
50
+ ? (
51
+ <span>
52
+ <Icon fixedWidth
53
+ icon="clock"
67
54
  />
68
- )}
69
- </>
70
- ) : (
55
+ {" "}
56
+ </span>
57
+ )
58
+ : (
71
59
  <>
72
- <Caption
73
- color="light"
74
- tag="span"
75
- text={dateTimestamp.toTimeWithMeridian()}
76
- />{" "}
77
- {showTimezone && (
78
- <Caption
79
- color="light"
60
+ <Body color="light"
80
61
  tag="span"
81
- text={dateTimestamp.toTimezone()}
62
+ >
63
+ <Icon fixedWidth
64
+ icon="clock"
65
+ size={size === "md" ? "" : "sm"}
82
66
  />
83
- )}
67
+ {" "}
68
+ </Body>
84
69
  </>
85
- )}
70
+ )
71
+ )}
72
+
73
+ <time dateTime={date}>
74
+ <span>
75
+ {unstyled
76
+ ? (
77
+ <>
78
+ <span>
79
+ {dateTimestamp.toTimeWithMeridian()}
80
+ </span>
81
+ {" "}
82
+ {showTimezone && (
83
+ <span>
84
+ {dateTimestamp.toTimezone()}
85
+ </span>
86
+ )}
87
+ </>
88
+ )
89
+ : size === "md"
90
+ ? (
91
+ <>
92
+ <Body
93
+ className="pb_time"
94
+ tag="span"
95
+ text={dateTimestamp.toTimeWithMeridian()}
96
+ />{" "}
97
+ {showTimezone && (
98
+ <Body
99
+ color="light"
100
+ tag="span"
101
+ text={dateTimestamp.toTimezone()}
102
+ />
103
+ )}
104
+ </>
105
+ )
106
+ : (
107
+ <>
108
+ <Caption
109
+ color="light"
110
+ tag="span"
111
+ text={dateTimestamp.toTimeWithMeridian()}
112
+ />{" "}
113
+ {showTimezone && (
114
+ <Caption
115
+ color="light"
116
+ tag="span"
117
+ text={dateTimestamp.toTimezone()}
118
+ />
119
+ )}
120
+ </>
121
+ )}
86
122
  </span>
87
123
  </time>
88
124
  </div>
@@ -0,0 +1,37 @@
1
+ <%= pb_rails("caption", props: { size: "xs", text: "Example with no year" }) %>
2
+
3
+ <%= pb_rails("time", props: {
4
+ show_icon: true,
5
+ show_timezone: true,
6
+ time: DateTime.now,
7
+ timezone: "America/New_York",
8
+ unstyled: true
9
+ }) %>
10
+
11
+ <br />
12
+
13
+ <%= pb_rails("caption", props: { size: "xs", text: "Example with wrapping typography kit" }) %>
14
+
15
+ <%= pb_rails("title", props: { size: 1 }) do %>
16
+ <%= pb_rails("time", props: {
17
+ show_icon: true,
18
+ show_timezone: true,
19
+ time: DateTime.now,
20
+ timezone: "America/New_York",
21
+ unstyled: true
22
+ }) %>
23
+ <% end %>
24
+
25
+ <br />
26
+
27
+ <%= pb_rails("caption", props: { size: "xs", text: "Example with icon + subcaption" }) %>
28
+
29
+ <%= pb_rails("caption", props: { size: "xs" }) do %>
30
+ <%= pb_rails("time", props: {
31
+ show_icon: true,
32
+ show_timezone: true,
33
+ time: DateTime.now,
34
+ timezone: "America/New_York",
35
+ unstyled: true
36
+ }) %>
37
+ <% end %>