sveltekit-ui 1.1.17 → 1.1.18

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (199) hide show
  1. package/dist/Components/Alert/index.svelte +88 -0
  2. package/dist/Components/Alert/index.svelte.js +101 -0
  3. package/dist/Components/ArrowToggle/index.svelte +62 -0
  4. package/dist/Components/Attachment/index.svelte +77 -0
  5. package/dist/Components/Attachment/index.svelte.js +119 -0
  6. package/dist/Components/Audio/index.svelte +193 -0
  7. package/dist/Components/Audio/index.svelte.js +463 -0
  8. package/dist/Components/AudioEditor/index.svelte +252 -0
  9. package/dist/Components/AudioEditor/index.svelte.js +977 -0
  10. package/dist/Components/AudioEditor/samples/alloy-voice-sample.mp3 +0 -0
  11. package/dist/Components/AudioEditor/samples/echo-voice-sample.mp3 +0 -0
  12. package/dist/Components/AudioEditor/samples/fable-voice-sample.mp3 +0 -0
  13. package/dist/Components/AudioEditor/samples/nova-voice-sample.mp3 +0 -0
  14. package/dist/Components/AudioEditor/samples/onyx-voice-sample.mp3 +0 -0
  15. package/dist/Components/AudioEditor/samples/shimmer-voice-sample.mp3 +0 -0
  16. package/dist/Components/AuthCodeInput/index.svelte +85 -0
  17. package/dist/Components/AuthCodeInput/index.svelte.js +95 -0
  18. package/dist/Components/Breadcrumbs/index.svelte +27 -0
  19. package/dist/Components/Breadcrumbs/index.svelte.js +88 -0
  20. package/dist/Components/Button/index.svelte +721 -0
  21. package/dist/Components/Button/index.svelte.js +375 -0
  22. package/dist/Components/Chart/Klines/index.svelte +87 -0
  23. package/dist/Components/Chart/index.svelte +226 -0
  24. package/dist/Components/Chart/index.svelte.js +1090 -0
  25. package/dist/Components/ChartInput/DisplayNav/Klines/index.svelte +150 -0
  26. package/dist/Components/ChartInput/DisplayNav/Lines/index.svelte +45 -0
  27. package/dist/Components/ChartInput/DisplayNav/index.svelte +297 -0
  28. package/dist/Components/ChartInput/EditPanel/index.svelte +155 -0
  29. package/dist/Components/ChartInput/index.svelte +21 -0
  30. package/dist/Components/ChartInput/index.svelte.js +671 -0
  31. package/dist/Components/Checkbox/index.svelte +411 -0
  32. package/dist/Components/Checkbox/index.svelte.js +178 -0
  33. package/dist/Components/Code/index.svelte +23 -0
  34. package/dist/Components/Code/index.svelte.js +33 -0
  35. package/dist/Components/Color/index.svelte +51 -0
  36. package/dist/Components/Color/index.svelte.js +31 -0
  37. package/dist/Components/ColorInput/ChromaPicker/index.svelte +50 -0
  38. package/dist/Components/ColorInput/ColorPalette/index.svelte +62 -0
  39. package/dist/Components/ColorInput/OpacityPicker/index.svelte +68 -0
  40. package/dist/Components/ColorInput/ShowcasePicker/index.svelte +136 -0
  41. package/dist/Components/ColorInput/index.svelte +70 -0
  42. package/dist/Components/ColorInput/index.svelte.js +386 -0
  43. package/dist/Components/ConditionsInput/index.svelte +46 -0
  44. package/dist/Components/ConditionsInput/index.svelte.js +201 -0
  45. package/dist/Components/Confetti/index.svelte +98 -0
  46. package/dist/Components/Confetti/index.svelte.js +94 -0
  47. package/dist/Components/Content/index.svelte +500 -0
  48. package/dist/Components/Content/index.svelte.js +910 -0
  49. package/dist/Components/ContentInput/AttributesInput/CustomConfig/Audio/index.svelte +31 -0
  50. package/dist/Components/ContentInput/AttributesInput/CustomConfig/Audio/index.svelte.js +258 -0
  51. package/dist/Components/ContentInput/AttributesInput/CustomConfig/AudioAdvanced/index.svelte +31 -0
  52. package/dist/Components/ContentInput/AttributesInput/CustomConfig/AudioAdvanced/index.svelte.js +258 -0
  53. package/dist/Components/ContentInput/AttributesInput/CustomConfig/Dropdown/index.svelte +58 -0
  54. package/dist/Components/ContentInput/AttributesInput/CustomConfig/Dropdown/index.svelte.js +206 -0
  55. package/dist/Components/ContentInput/AttributesInput/CustomConfig/Image/index.svelte +28 -0
  56. package/dist/Components/ContentInput/AttributesInput/CustomConfig/Image/index.svelte.js +224 -0
  57. package/dist/Components/ContentInput/AttributesInput/CustomConfig/Number/index.svelte +44 -0
  58. package/dist/Components/ContentInput/AttributesInput/CustomConfig/Number/index.svelte.js +272 -0
  59. package/dist/Components/ContentInput/AttributesInput/CustomConfig/Qr/index.svelte +41 -0
  60. package/dist/Components/ContentInput/AttributesInput/CustomConfig/Qr/index.svelte.js +202 -0
  61. package/dist/Components/ContentInput/AttributesInput/CustomConfig/Slider/index.svelte +19 -0
  62. package/dist/Components/ContentInput/AttributesInput/CustomConfig/Slider/index.svelte.js +117 -0
  63. package/dist/Components/ContentInput/AttributesInput/CustomConfig/TableAdvanced/index.svelte +60 -0
  64. package/dist/Components/ContentInput/AttributesInput/CustomConfig/TableAdvanced/index.svelte.js +542 -0
  65. package/dist/Components/ContentInput/AttributesInput/CustomConfig/Tag/index.svelte +47 -0
  66. package/dist/Components/ContentInput/AttributesInput/CustomConfig/Tag/index.svelte.js +185 -0
  67. package/dist/Components/ContentInput/AttributesInput/CustomConfig/TextInput/index.svelte +35 -0
  68. package/dist/Components/ContentInput/AttributesInput/CustomConfig/TextInput/index.svelte.js +222 -0
  69. package/dist/Components/ContentInput/AttributesInput/CustomConfig/TimeInput/index.svelte +20 -0
  70. package/dist/Components/ContentInput/AttributesInput/CustomConfig/TimeInput/index.svelte.js +84 -0
  71. package/dist/Components/ContentInput/AttributesInput/DefinedTypeInput/index.svelte +25 -0
  72. package/dist/Components/ContentInput/AttributesInput/DefinedTypeInput/index.svelte.js +91 -0
  73. package/dist/Components/ContentInput/AttributesInput/index.svelte +352 -0
  74. package/dist/Components/ContentInput/AttributesInput/index.svelte.js +1436 -0
  75. package/dist/Components/ContentInput/ContentPanelBuilder/AddElement/index.svelte +64 -0
  76. package/dist/Components/ContentInput/ContentPanelBuilder/AddElement/index.svelte.js +97 -0
  77. package/dist/Components/ContentInput/ContentPanelBuilder/ElementList/index.svelte +184 -0
  78. package/dist/Components/ContentInput/ContentPanelBuilder/index.svelte +41 -0
  79. package/dist/Components/ContentInput/index.svelte +78 -0
  80. package/dist/Components/ContentInput/index.svelte.js +1197 -0
  81. package/dist/Components/CronInput/index.svelte +78 -0
  82. package/dist/Components/CronInput/index.svelte.js +198 -0
  83. package/dist/Components/DataTypeInput/index.svelte +174 -0
  84. package/dist/Components/DataTypeInput/index.svelte.js +565 -0
  85. package/dist/Components/Dropdown/index.svelte +116 -0
  86. package/dist/Components/Dropdown/index.svelte.js +403 -0
  87. package/dist/Components/EmailAddress/index.svelte +22 -0
  88. package/dist/Components/EmailAddress/index.svelte.js +45 -0
  89. package/dist/Components/ErrorX/index.svelte +58 -0
  90. package/dist/Components/Eye/index.svelte +57 -0
  91. package/dist/Components/FileInput/index.svelte +146 -0
  92. package/dist/Components/FileInput/index.svelte.js +225 -0
  93. package/dist/Components/Hamburger/index.svelte +99 -0
  94. package/dist/Components/HorizScrollBox/index.svelte +145 -0
  95. package/dist/Components/Icon/index.svelte +412 -0
  96. package/dist/Components/Icon/index.svelte.js +116 -0
  97. package/dist/Components/IconInput/index.svelte +77 -0
  98. package/dist/Components/IconInput/index.svelte.js +259 -0
  99. package/dist/Components/Image/index.svelte +126 -0
  100. package/dist/Components/Image/index.svelte.js +116 -0
  101. package/dist/Components/ImageEditor/Image/CropBox/index.svelte +165 -0
  102. package/dist/Components/ImageEditor/Image/index.svelte +104 -0
  103. package/dist/Components/ImageEditor/Panels/AI/index.svelte +44 -0
  104. package/dist/Components/ImageEditor/Panels/Crop/index.svelte +96 -0
  105. package/dist/Components/ImageEditor/Panels/File/QualityPicker/index.svelte +124 -0
  106. package/dist/Components/ImageEditor/Panels/File/index.svelte +74 -0
  107. package/dist/Components/ImageEditor/Panels/Filters/index.svelte +46 -0
  108. package/dist/Components/ImageEditor/Panels/Resize/index.svelte +58 -0
  109. package/dist/Components/ImageEditor/index.svelte +93 -0
  110. package/dist/Components/ImageEditor/index.svelte.js +1961 -0
  111. package/dist/Components/ImageSlider/index.svelte +124 -0
  112. package/dist/Components/ImageSlider/index.svelte.js +99 -0
  113. package/dist/Components/InfoBox/index.svelte +89 -0
  114. package/dist/Components/Json/Nested/index.svelte +157 -0
  115. package/dist/Components/Json/index.svelte +60 -0
  116. package/dist/Components/Json/index.svelte.js +594 -0
  117. package/dist/Components/LabeledItem/index.svelte +102 -0
  118. package/dist/Components/Layout/NavBar/FullNav/index.svelte +52 -0
  119. package/dist/Components/Layout/NavBar/NavGuts/index.svelte +87 -0
  120. package/dist/Components/Layout/NavBar/index.svelte +72 -0
  121. package/dist/Components/Layout/index.svelte +149 -0
  122. package/dist/Components/Layout/index.svelte.js +360 -0
  123. package/dist/Components/Link/index.svelte +47 -0
  124. package/dist/Components/Link/index.svelte.js +136 -0
  125. package/dist/Components/LoadingSuccessDiv/index.svelte +51 -0
  126. package/dist/Components/LoadingWheel/index.svelte +38 -0
  127. package/dist/Components/Location/index.svelte +79 -0
  128. package/dist/Components/Location/index.svelte.js +288 -0
  129. package/dist/Components/LocationInput/index.svelte +197 -0
  130. package/dist/Components/LocationInput/index.svelte.js +965 -0
  131. package/dist/Components/Number/index.svelte +47 -0
  132. package/dist/Components/Number/index.svelte.js +151 -0
  133. package/dist/Components/PhoneCountryCode/index.svelte +7 -0
  134. package/dist/Components/PhoneCountryCode/index.svelte.js +260 -0
  135. package/dist/Components/PhoneNumber/index.svelte +22 -0
  136. package/dist/Components/PhoneNumber/index.svelte.js +41 -0
  137. package/dist/Components/Popover/index.svelte +396 -0
  138. package/dist/Components/Popover/index.svelte.js +319 -0
  139. package/dist/Components/Qr/index.svelte +85 -0
  140. package/dist/Components/Qr/index.svelte.js +301 -0
  141. package/dist/Components/QrInput/index.svelte +47 -0
  142. package/dist/Components/QrInput/index.svelte.js +218 -0
  143. package/dist/Components/Slider/index.svelte +239 -0
  144. package/dist/Components/Slider/index.svelte.js +469 -0
  145. package/dist/Components/Spacer/index.svelte +41 -0
  146. package/dist/Components/StoragePicker/DisplayFile/index.svelte +15 -0
  147. package/dist/Components/StoragePicker/index.svelte +187 -0
  148. package/dist/Components/StoragePicker/index.svelte.js +592 -0
  149. package/dist/Components/SuccessCheck/index.svelte +56 -0
  150. package/dist/Components/TableAdvanced/ColumnInput/index.svelte +117 -0
  151. package/dist/Components/TableAdvanced/ColumnInput/index.svelte.js +456 -0
  152. package/dist/Components/TableAdvanced/FilterInput/index.svelte +54 -0
  153. package/dist/Components/TableAdvanced/FilterInput/index.svelte.js +247 -0
  154. package/dist/Components/TableAdvanced/Pagination/index.svelte +43 -0
  155. package/dist/Components/TableAdvanced/Pagination/index.svelte.js +97 -0
  156. package/dist/Components/TableAdvanced/SortByInput/index.svelte +72 -0
  157. package/dist/Components/TableAdvanced/SortByInput/index.svelte.js +176 -0
  158. package/dist/Components/TableAdvanced/index.svelte +275 -0
  159. package/dist/Components/TableAdvanced/index.svelte.js +1565 -0
  160. package/dist/Components/Tag/index.svelte +45 -0
  161. package/dist/Components/Tag/index.svelte.js +76 -0
  162. package/dist/Components/TextArrayInput/index.svelte +108 -0
  163. package/dist/Components/TextArrayInput/index.svelte.js +239 -0
  164. package/dist/Components/TextInput/PasswordTooltip/index.svelte +89 -0
  165. package/dist/Components/TextInput/index.svelte +223 -0
  166. package/dist/Components/TextInput/index.svelte.js +447 -0
  167. package/dist/Components/Time/index.svelte +7 -0
  168. package/dist/Components/Time/index.svelte.js +38 -0
  169. package/dist/Components/TimeInput/NumberToggler/index.svelte +34 -0
  170. package/dist/Components/TimeInput/NumberToggler/index.svelte.js +79 -0
  171. package/dist/Components/TimeInput/index.js +702 -0
  172. package/dist/Components/TimeInput/index.svelte +211 -0
  173. package/dist/Components/TimeInput/index.svelte.js +638 -0
  174. package/dist/Components/Tooltip/index.svelte +143 -0
  175. package/dist/Components/TransparentBackground/index.svelte +153 -0
  176. package/dist/Components/TypingDots/index.svelte +84 -0
  177. package/dist/Components/VariablePathInput/index.svelte +63 -0
  178. package/dist/Components/VariablePathInput/index.svelte.js +273 -0
  179. package/dist/Components/VideoTBD/index.svelte +100 -0
  180. package/dist/Components/XFollow/index.svelte +42 -0
  181. package/dist/Components/XPost/index.svelte +52 -0
  182. package/dist/Components/XPost/index.svelte.js +64 -0
  183. package/dist/Components/YoutubeChannelButton/index.svelte +82 -0
  184. package/dist/Components/YoutubeVideo/index.svelte +73 -0
  185. package/dist/Components/YoutubeVideo/index.svelte.js +54 -0
  186. package/dist/actions/draggable.js +49 -0
  187. package/dist/actions/index.js +24 -0
  188. package/dist/actions/no_spaces.js +33 -0
  189. package/dist/actions/numbers_only.js +26 -0
  190. package/dist/actions/scroll_y.js +28 -0
  191. package/dist/actions/stop_scroll_propagation_y.js +42 -0
  192. package/dist/actions/swipe_handler.js +295 -0
  193. package/dist/client/astc_formatting/index.js +1128 -0
  194. package/dist/client/docs/index.js +7622 -0
  195. package/dist/client/index.js +735 -0
  196. package/dist/client/types/index.js +2812 -0
  197. package/dist/index.js +180 -0
  198. package/dist/style.css +682 -0
  199. package/package.json +1 -1
@@ -0,0 +1,702 @@
1
+ export const time_formats = {
2
+ time_full: {
3
+ name: "Time Full",
4
+ example: {
5
+ year: 2024,
6
+ month: 1,
7
+ day: 1,
8
+ hour: 0,
9
+ minute: 0,
10
+ second: 0,
11
+ datetime: null,
12
+ datetime_utc: null,
13
+ datetime_zoned: null,
14
+ },
15
+ },
16
+ epoch: {
17
+ name: "Epoch (seconds)",
18
+ example: "1724433112",
19
+ needs_granularity: true,
20
+ },
21
+ datetime: {
22
+ name: "Datetime",
23
+ example: "2024-08-23T16:04",
24
+ needs_granularity: true,
25
+ },
26
+ datetime_utc: {
27
+ name: "Datetime UTC",
28
+ example: "2024-08-23T16:04Z",
29
+ needs_granularity: true,
30
+ },
31
+ datetime_zoned: {
32
+ name: "Datetime Zoned",
33
+ example: "2024-08-23T16:04-04:00",
34
+ needs_granularity: true,
35
+ },
36
+ calendar_date: {
37
+ name: "Calendar Date",
38
+ example: "2024-08-23",
39
+ },
40
+ year: {
41
+ name: "Year",
42
+ example: "2024",
43
+ },
44
+ year_month: {
45
+ name: "Year-Month (yyyy-mm)",
46
+ example: "2024-07",
47
+ },
48
+ year_week: {
49
+ name: "Year-Week (yyyy-Www)",
50
+ example: "2024-W32",
51
+ },
52
+ hour_minute: {
53
+ name: "Hour-Minute (hh:mm)",
54
+ example: "12:47",
55
+ },
56
+ hour_minute_second: {
57
+ name: "Hour-Minute-Second (hh:mm:ss)",
58
+ example: "12:47:09",
59
+ },
60
+ hour_minute_second: {
61
+ name: "Hour-Minute-Second (hh:mm:ss)",
62
+ example: "12:47:09",
63
+ },
64
+ period_full: {
65
+ name: "Period Full",
66
+ example: {
67
+ years: 1,
68
+ months: 2,
69
+ days: 3,
70
+ hours: 4,
71
+ minutes: 5,
72
+ seconds: 6,
73
+ },
74
+ },
75
+ period_iso_8601: {
76
+ name: "Period ISO 8601",
77
+ example: "P3DT4H5M6S",
78
+ },
79
+ period_total_seconds: {
80
+ name: "Period Total Seconds",
81
+ example: "1000000",
82
+ },
83
+ }
84
+
85
+ export const granularities = ["year", "month", "week", "day", "hour", "minute", "second"]
86
+
87
+ export const month_names = [
88
+ "January",
89
+ "February",
90
+ "March",
91
+ "April",
92
+ "May",
93
+ "June",
94
+ "July",
95
+ "August",
96
+ "September",
97
+ "October",
98
+ "November",
99
+ "December",
100
+ ]
101
+
102
+ export const days_of_week_names = ["Sunday", "Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday"]
103
+
104
+ export const common_timezones = [
105
+ { text: "America/New_York", offset: "-04:00" },
106
+ { text: "America/Los_Angeles", offset: "-07:00" },
107
+ { text: "America/Chicago", offset: "-05:00" },
108
+ { text: "America/Denver", offset: "-06:00" },
109
+ { text: "America/Toronto", offset: "-04:00" },
110
+ { text: "America/Mexico_City", offset: "-06:00" },
111
+ { text: "America/Sao_Paulo", offset: "-03:00" },
112
+ { text: "America/Buenos_Aires", offset: "-03:00" },
113
+ { text: "Europe/London", offset: "+01:00" },
114
+ { text: "Europe/Paris", offset: "+02:00" },
115
+ { text: "Europe/Berlin", offset: "+02:00" },
116
+ { text: "Europe/Madrid", offset: "+02:00" },
117
+ { text: "Europe/Rome", offset: "+02:00" },
118
+ { text: "Europe/Amsterdam", offset: "+02:00" },
119
+ { text: "Europe/Athens", offset: "+03:00" },
120
+ { text: "Europe/Moscow", offset: "+03:00" },
121
+ { text: "Africa/Cairo", offset: "+03:00" },
122
+ { text: "Africa/Johannesburg", offset: "+02:00" },
123
+ { text: "Asia/Jerusalem", offset: "+03:00" },
124
+ { text: "Asia/Riyadh", offset: "+03:00" },
125
+ { text: "Asia/Dubai", offset: "+04:00" },
126
+ { text: "Asia/Tehran", offset: "+03:30" },
127
+ { text: "Asia/Karachi", offset: "+05:00" },
128
+ { text: "Asia/Kolkata", offset: "+05:30" },
129
+ { text: "Asia/Dhaka", offset: "+06:00" },
130
+ { text: "Asia/Bangkok", offset: "+07:00" },
131
+ { text: "Asia/Jakarta", offset: "+07:00" },
132
+ { text: "Asia/Shanghai", offset: "+08:00" },
133
+ { text: "Asia/Hong_Kong", offset: "+08:00" },
134
+ { text: "Asia/Tokyo", offset: "+09:00" },
135
+ { text: "Asia/Seoul", offset: "+09:00" },
136
+ { text: "Australia/Sydney", offset: "+10:00" },
137
+ { text: "Australia/Melbourne", offset: "+10:00" },
138
+ { text: "Australia/Perth", offset: "+08:00" },
139
+ { text: "Pacific/Auckland", offset: "+12:00" },
140
+ { text: "Pacific/Honolulu", offset: "-10:00" },
141
+ { text: "Asia/Kuala_Lumpur", offset: "+08:00" },
142
+ { text: "Asia/Singapore", offset: "+08:00" },
143
+ { text: "Asia/Manila", offset: "+08:00" },
144
+ { text: "Asia/Taipei", offset: "+08:00" },
145
+ { text: "Europe/Istanbul", offset: "+03:00" },
146
+ { text: "Europe/Warsaw", offset: "+02:00" },
147
+ { text: "Europe/Lisbon", offset: "+01:00" },
148
+ { text: "Europe/Dublin", offset: "+01:00" },
149
+ { text: "Asia/Beirut", offset: "+03:00" },
150
+ { text: "Europe/Helsinki", offset: "+03:00" },
151
+ { text: "Africa/Lagos", offset: "+01:00" },
152
+ { text: "Africa/Nairobi", offset: "+03:00" },
153
+ { text: "Asia/Kathmandu", offset: "+05:45" },
154
+ { text: "Asia/Colombo", offset: "+05:30" },
155
+ ]
156
+
157
+ export function period_iso_8601_to_period_full(input) {
158
+ let from_period_iso_8601 = {
159
+ days: null,
160
+ hours: null,
161
+ minutes: null,
162
+ seconds: null,
163
+ }
164
+ if (input) {
165
+ const regex = /P(?:(\d+)Y)?(?:(\d+)M)?(?:(\d+)D)?(?:T(?:(\d+)H)?(?:(\d+)M)?(?:(\d+)S)?)?/
166
+ const matches = input.match(regex)
167
+ if (matches) {
168
+ from_period_iso_8601.days = matches[3] ? parseInt(matches[3], 10) : null
169
+ from_period_iso_8601.hours = matches[4] ? parseInt(matches[4], 10) : null
170
+ from_period_iso_8601.minutes = matches[5] ? parseInt(matches[5], 10) : null
171
+ from_period_iso_8601.seconds = matches[6] ? parseInt(matches[6], 10) : null
172
+ }
173
+ }
174
+ return from_period_iso_8601
175
+ }
176
+
177
+ export function total_seconds_to_period_full(input) {
178
+ let from_total_seconds = {
179
+ days: null,
180
+ hours: null,
181
+ minutes: null,
182
+ seconds: null,
183
+ }
184
+ if (input != null) {
185
+ let remaining_seconds = Number.isInteger(input) ? input : 0
186
+ const seconds_in_day = 86400
187
+ const seconds_in_hour = 3600
188
+ const seconds_in_minute = 60
189
+ from_total_seconds.days = Math.floor(remaining_seconds / seconds_in_day)
190
+ remaining_seconds %= seconds_in_day
191
+ from_total_seconds.hours = Math.floor(remaining_seconds / seconds_in_hour)
192
+ remaining_seconds %= seconds_in_hour
193
+ from_total_seconds.minutes = Math.floor(remaining_seconds / seconds_in_minute)
194
+ remaining_seconds %= seconds_in_minute
195
+ from_total_seconds.seconds = remaining_seconds
196
+ }
197
+ return from_total_seconds
198
+ }
199
+
200
+ export function period_full_parts_to_full(input, from_period_iso_8601, from_total_seconds) {
201
+ let period_full = {
202
+ days: input?.days ?? from_period_iso_8601?.days ?? from_total_seconds?.days ?? null,
203
+ hours: input?.hours ?? from_period_iso_8601?.hours ?? from_total_seconds?.hours ?? null,
204
+ minutes: input?.minutes ?? from_period_iso_8601?.minutes ?? from_total_seconds?.minutes ?? null,
205
+ seconds: input?.seconds ?? from_period_iso_8601?.seconds ?? from_total_seconds?.seconds ?? null,
206
+ iso_8601: null,
207
+ total_seconds: null,
208
+ content: null,
209
+ }
210
+ period_full.iso_8601 = `P${period_full.days ? period_full.days + "D" : ""}T${
211
+ period_full.hours ? period_full.hours + "H" : ""
212
+ }${period_full.minutes ? period_full.minutes + "M" : ""}${period_full.seconds ? period_full.seconds + "S" : ""}`
213
+ period_full.total_seconds =
214
+ (period_full.days || 0) * 24 * 60 * 60 +
215
+ (period_full.hours || 0) * 60 * 60 +
216
+ (period_full.minutes || 0) * 60 +
217
+ (period_full.seconds || 0)
218
+ let content_items = []
219
+ if (Number.isInteger(period_full.days)) {
220
+ content_items.push(`${period_full.days} day${period_full.days > 1 ? "s" : ""}`)
221
+ }
222
+ if (Number.isInteger(period_full.hours)) {
223
+ content_items.push(`${period_full.hours} hour${period_full.hours > 1 ? "s" : ""}`)
224
+ }
225
+ if (Number.isInteger(period_full.minutes)) {
226
+ content_items.push(`${period_full.minutes} minute${period_full.minutes > 1 ? "s" : ""}`)
227
+ }
228
+ if (Number.isInteger(period_full.seconds)) {
229
+ content_items.push(`${period_full.seconds} second${period_full.seconds > 1 ? "s" : ""}`)
230
+ }
231
+ period_full.content = content_items.join(", ")
232
+ return period_full
233
+ }
234
+
235
+ export function get_time_full_from_object(val_loc) {
236
+ let time_full = {
237
+ epoch: null,
238
+ granularity: val_loc?.granularity ?? null,
239
+ year: null,
240
+ month: null,
241
+ day_of_month: null,
242
+ day_of_week: null,
243
+ day_of_year: null,
244
+ week_of_year: null,
245
+ hour: null,
246
+ minute: null,
247
+ second: null,
248
+ timezone:
249
+ val_loc?.timezone && common_timezones.some((h) => h?.text == val_loc?.timezone)
250
+ ? val_loc?.timezone
251
+ : Intl.DateTimeFormat().resolvedOptions().timeZone,
252
+ datetime: null,
253
+ datetime_zoned: null,
254
+ datetime_utc: null,
255
+ content: null,
256
+ }
257
+ if (val_loc?.is_null) {
258
+ return time_full
259
+ }
260
+ let date = null
261
+ let date_from_epoch = Number.isInteger(val_loc?.epoch) ? new Date(val_loc?.epoch * 1000) : null
262
+ if (val_loc?.format == "epoch" && date_from_epoch) {
263
+ date = date_from_epoch
264
+ } else {
265
+ date = new Date(0)
266
+ for (let granularity of granularities) {
267
+ if (granularity == "year") {
268
+ if (Number.isInteger(val_loc?.year) && val_loc.year > -10000 && val_loc.year < 10000) {
269
+ date.setFullYear(val_loc.year)
270
+ } else {
271
+ let temp_date = date_from_epoch ?? new Date()
272
+ date.setFullYear(temp_date.getFullYear())
273
+ }
274
+ } else if (granularity == "month") {
275
+ if (Number.isInteger(val_loc?.month) && val_loc?.month > 0 && val_loc?.month < 13) {
276
+ date.setDate(1)
277
+ date.setMonth(val_loc?.month > 0 ? val_loc.month - 1 : 0)
278
+ } else if (date_from_epoch) {
279
+ date.setMonth(date_from_epoch?.getMonth())
280
+ }
281
+ } else if (granularity == "day") {
282
+ if (Number.isInteger(val_loc?.day_of_month) && val_loc?.day_of_month > 0 && val_loc?.day_of_month < 32) {
283
+ const days_in_month = new Date(date.getFullYear(), date.getMonth() + 1, 0).getDate()
284
+ date.setDate(Math.min(val_loc?.day_of_month > 0 ? val_loc.day_of_month : 1, days_in_month))
285
+ } else if (date_from_epoch) {
286
+ date.setDate(date_from_epoch.getDate())
287
+ }
288
+ } else if (granularity == "hour") {
289
+ if (Number.isInteger(val_loc?.hour) && val_loc?.hour > -1 && val_loc?.hour < 24) {
290
+ date.setHours(val_loc?.hour > -1 ? val_loc.hour : 0)
291
+ } else if (date_from_epoch) {
292
+ date.setHours(date_from_epoch.getHours())
293
+ }
294
+ } else if (granularity == "minute") {
295
+ if (Number.isInteger(val_loc?.minute) && val_loc?.minute > -1 && val_loc?.minute < 61) {
296
+ date.setMinutes(val_loc?.minute > -1 ? val_loc.minute : 0)
297
+ } else if (date_from_epoch) {
298
+ date.setMinutes(date_from_epoch.getMinutes())
299
+ }
300
+ } else if (granularity == "second") {
301
+ if (Number.isInteger(val_loc?.second) && val_loc?.second > -1 && val_loc?.second < 60) {
302
+ date.setSeconds(val_loc?.second > -1 ? val_loc.second : 0)
303
+ } else if (date_from_epoch) {
304
+ date.setSeconds(date_from_epoch.getSeconds())
305
+ }
306
+ }
307
+ if (time_full.granularity === granularity) {
308
+ break
309
+ }
310
+ }
311
+ }
312
+ if (!date) {
313
+ return time_full
314
+ }
315
+ time_full.epoch = Math.floor(date.getTime() / 1000)
316
+ let date_formatter = new Intl.DateTimeFormat("en-US", {
317
+ year: "numeric",
318
+ month: "numeric",
319
+ day: "2-digit",
320
+ hour: "2-digit",
321
+ minute: "2-digit",
322
+ second: "2-digit",
323
+ hour12: false,
324
+ timeZone: time_full?.timezone,
325
+ })
326
+ let parts = date_formatter.formatToParts(date)
327
+ let date_components = {}
328
+ for (let part of parts) {
329
+ if (part.type === "year") {
330
+ date_components.year = +part.value
331
+ } else if (part.type === "month") {
332
+ date_components.month = +part.value
333
+ } else if (part.type === "day") {
334
+ date_components.day = +part.value
335
+ } else if (part.type === "hour") {
336
+ date_components.hour = +part.value == 24 ? 0 : +part.value
337
+ } else if (part.type === "minute") {
338
+ date_components.minute = +part.value
339
+ } else if (part.type === "second") {
340
+ date_components.second = +part.value
341
+ }
342
+ }
343
+ if (
344
+ !val_loc?.format ||
345
+ ["time_full", "epoch", "datetime", "datetime_utc", "datetime_zoned", "calendar_date"].includes(val_loc?.format)
346
+ ) {
347
+ for (let granularity of granularities) {
348
+ if (granularity == "year") {
349
+ time_full.year = date_components.year
350
+ time_full.content = `${time_full.year}`
351
+ time_full.datetime = `${time_full.year.toString().padStart(4, "0")}`
352
+ } else if (granularity == "month") {
353
+ time_full.month = date_components.month
354
+ time_full.content = `${month_names[time_full.month - 1]}, ${time_full.year}`
355
+ time_full.datetime = `${time_full.year.toString().padStart(4, "0")}-${time_full.month
356
+ .toString()
357
+ .padStart(2, "0")}`
358
+ } else if (granularity == "week") {
359
+ let first_day_of_year = new Date(date.getFullYear(), 0, 1)
360
+ let past_days_of_year = (date - first_day_of_year) / 86400000
361
+ time_full.week_of_year = Math.ceil((past_days_of_year + first_day_of_year.getDay() + 1) / 7)
362
+ time_full.content = `Week ${time_full.week_of_year}, ${time_full.year}`
363
+ } else if (granularity == "day") {
364
+ time_full.day_of_month = date_components.day
365
+ time_full.day_of_week = date.getDay()
366
+ let start_of_year = new Date(date.getFullYear(), 0, 0)
367
+ let diff = date - start_of_year + (start_of_year.getTimezoneOffset() - date.getTimezoneOffset()) * 60 * 1000
368
+ time_full.day_of_year = Math.floor(diff / (1000 * 60 * 60 * 24))
369
+ time_full.content = `${days_of_week_names[time_full.day_of_week]}, ${month_names[time_full.month - 1]} ${
370
+ time_full.day_of_month
371
+ }, ${time_full.year}`
372
+ time_full.datetime = `${time_full.year.toString().padStart(4, "0")}-${time_full.month
373
+ .toString()
374
+ .padStart(2, "0")}-${time_full.day_of_month.toString().padStart(2, "0")}`
375
+ } else if (granularity == "hour") {
376
+ time_full.hour = date_components.hour
377
+ time_full.content = `${time_full.month}/${time_full.day_of_month}/${time_full.year} ${time_full.hour}:00`
378
+ time_full.datetime = `${time_full.year.toString().padStart(4, "0")}-${time_full.month
379
+ .toString()
380
+ .padStart(2, "0")}-${time_full.day_of_month.toString().padStart(2, "0")}T${time_full.hour
381
+ .toString()
382
+ .padStart(2, "0")}`
383
+ } else if (granularity == "minute") {
384
+ time_full.minute = date_components.minute
385
+ time_full.content = `${time_full.month}/${time_full.day_of_month}/${time_full.year} ${
386
+ time_full.hour
387
+ }:${time_full.minute.toString().padStart(2, "0")}`
388
+ time_full.datetime = `${time_full.year.toString().padStart(4, "0")}-${time_full.month
389
+ .toString()
390
+ .padStart(2, "0")}-${time_full.day_of_month.toString().padStart(2, "0")}T${time_full.hour
391
+ .toString()
392
+ .padStart(2, "0")}:${time_full.minute.toString().padStart(2, "0")}`
393
+ } else if (granularity == "second") {
394
+ time_full.second = date_components.second
395
+ time_full.content = `${time_full.month}/${time_full.day_of_month}/${time_full.year} ${
396
+ time_full.hour
397
+ }:${time_full.minute.toString().padStart(2, "0")}:${time_full.second.toString().padStart(2, "0")}`
398
+ time_full.datetime = `${time_full.year.toString().padStart(4, "0")}-${time_full.month
399
+ .toString()
400
+ .padStart(2, "0")}-${time_full.day_of_month.toString().padStart(2, "0")}T${time_full.hour
401
+ .toString()
402
+ .padStart(2, "0")}:${time_full.minute.toString().padStart(2, "0")}:${time_full.second
403
+ .toString()
404
+ .padStart(2, "0")}`
405
+ }
406
+ if (
407
+ (val_loc?.format != "calendar_date" && time_full.granularity == granularity) ||
408
+ (val_loc?.format == "calendar_date" && granularity == "day")
409
+ ) {
410
+ break
411
+ }
412
+ }
413
+ if (time_full?.timezone) {
414
+ const year = time_full.year !== null ? String(time_full.year).padStart(4, "0") : "0000"
415
+ const month = time_full.month !== null ? String(time_full.month).padStart(2, "0") : "00"
416
+ const day_of_month = time_full.day_of_month !== null ? String(time_full.day_of_month).padStart(2, "0") : "00"
417
+ const hour = time_full.hour !== null ? String(time_full.hour).padStart(2, "0") : "00"
418
+ const minute = time_full.minute !== null ? String(time_full.minute).padStart(2, "0") : "00"
419
+ const second = time_full.second !== null ? String(time_full.second).padStart(2, "0") : "00"
420
+ const full_datetime = `${year}-${month}-${day_of_month}T${hour}:${minute}:${second}`
421
+ time_full.datetime_utc = `${full_datetime}Z`
422
+ const date = new Date()
423
+ const formatter = new Intl.DateTimeFormat("en-US", {
424
+ timeZone: time_full?.timezone,
425
+ timeZoneName: "shortOffset",
426
+ hour12: false,
427
+ })
428
+ const parts = formatter.formatToParts(date)
429
+ let offset_string = parts.find((part) => part.type === "timeZoneName").value
430
+ offset_string = offset_string.replace(/GMT([+-]?)(\d{1,2})/, (match, sign, hours) => {
431
+ const padded_hours = hours.padStart(2, "0")
432
+ return `${sign}${padded_hours}:00`
433
+ })
434
+ time_full.datetime_zoned = `${full_datetime}${offset_string}[${time_full.timezone}]`
435
+ // tbd if we are handling epoch diff for set timezones
436
+ }
437
+ }
438
+ if (val_loc?.format == "calendar_date") {
439
+ time_full.content =
440
+ Number.isInteger(time_full?.year) &&
441
+ Number.isInteger(time_full?.month) &&
442
+ Number.isInteger(time_full?.day_of_month)
443
+ ? `${time_full?.year}-${time_full?.month}-${time_full?.day_of_month}`
444
+ : null
445
+ } else if (val_loc?.format == "year") {
446
+ time_full.year = date_components.year
447
+ time_full.content = date_components.year
448
+ } else if (val_loc?.format == "year_month") {
449
+ time_full.year = date_components.year
450
+ time_full.month = date_components.month
451
+ time_full.content = `${date_components.year}/${date_components.month}`
452
+ } else if (val_loc?.format == "year_week") {
453
+ time_full.year = date_components.year
454
+ let first_day_of_year = new Date(date.getFullYear(), 0, 1)
455
+ let past_days_of_year = (date - first_day_of_year) / 86400000
456
+ time_full.week_of_year = Math.ceil((past_days_of_year + first_day_of_year.getDay() + 1) / 7)
457
+ time_full.content = `${time_full.year}, Week ${time_full.week_of_year}`
458
+ } else if (val_loc?.format == "hour_minute") {
459
+ time_full.hour = date_components.hour
460
+ time_full.minute = date_components.minute
461
+ time_full.content =
462
+ Number.isInteger(time_full?.hour) && Number.isInteger(time_full?.minute)
463
+ ? `${time_full?.hour}:${time_full?.minute}`
464
+ : null
465
+ } else if (val_loc?.format == "hour_minute_second") {
466
+ time_full.hour = date_components.hour
467
+ time_full.minute = date_components.minute
468
+ time_full.second = date_components.second
469
+ time_full.content =
470
+ Number.isInteger(time_full?.hour) && Number.isInteger(time_full?.minute) && Number.isInteger(time_full?.second)
471
+ ? `${time_full?.hour}:${time_full?.minute}:${time_full?.second}`
472
+ : null
473
+ } else if (["period_full", "period_iso_8601", "period_total_seconds"].includes(val_loc?.format)) {
474
+ return period_full_parts_to_full(val_loc)
475
+ }
476
+ return time_full
477
+ }
478
+
479
+ export function get_time_object_from_val(input, format, granularity, timezone) {
480
+ if (!format) {
481
+ if (typeof input === "object") {
482
+ format = "time_full"
483
+ } else if (Number.isInteger(input)) {
484
+ format = "epoch"
485
+ } else if (typeof input === "string") {
486
+ if (/^\d{4}-\d{2}-\d{2}$/.test(input)) {
487
+ format = "calendar_date"
488
+ } else if (/^\d{4}-W\d{2}$/.test(input)) {
489
+ format = "year_week"
490
+ } else if (/^\d{4}-\d{2}$/.test(input)) {
491
+ format = "year_month"
492
+ } else if (/^\d{2}:\d{2}:\d{2}$/.test(input)) {
493
+ format = "hour_minute_second"
494
+ } else if (/^\d{2}:\d{2}$/.test(input)) {
495
+ format = "hour_minute"
496
+ } else if (/^\d{4}-\d{2}-\d{2}T\d{2}:\d{2}:\d{2}Z$/.test(input)) {
497
+ format = "datetime_utc"
498
+ } else if (/^\d{4}-\d{2}-\d{2}T\d{2}:\d{2}:\d{2}([+-]\d{2}:\d{2})?\[.*\]$/.test(input)) {
499
+ format = "datetime_zoned"
500
+ } else if (/^\d{4}-\d{2}-\d{2}T\d{2}:\d{2}:\d{2}$/.test(input)) {
501
+ format = "datetime"
502
+ }
503
+ }
504
+ }
505
+ if (format == "time_full") {
506
+ return get_time_full_from_object({
507
+ ...(input && typeof input == "object" && !Array.isArray(input) ? input : {}),
508
+ format,
509
+ })
510
+ } else if (format == "epoch") {
511
+ return get_time_full_from_object({
512
+ is_null: input == null,
513
+ epoch: input,
514
+ granularity: granularity,
515
+ timezone: timezone,
516
+ format: format,
517
+ })
518
+ } else if (format == "datetime") {
519
+ return get_time_full_from_object({
520
+ datetime: input,
521
+ granularity: granularity,
522
+ format: format,
523
+ })
524
+ } else if (format == "datetime_utc") {
525
+ return get_time_full_from_object({
526
+ datetime_utc: input,
527
+ granularity: granularity,
528
+ format: format,
529
+ })
530
+ } else if (format == "datetime_zoned") {
531
+ let timezone = null
532
+ if (input) {
533
+ const match = input.match(/\[(.+?)\]$/)
534
+ if (match) {
535
+ timezone = match[1]
536
+ } else {
537
+ const offset_match = input.match(/([+-]\d{2}:\d{2})/)
538
+ if (offset_match) {
539
+ const offset = offset_match[1]
540
+ timezone = common_timezones.find((h) => h?.offset == offset) || null
541
+ }
542
+ }
543
+ }
544
+ return get_time_full_from_object({
545
+ datetime_zoned: input,
546
+ granularity: granularity,
547
+ format: format,
548
+ timezone: timezone,
549
+ })
550
+ } else if (format == "calendar_date") {
551
+ let year = null
552
+ let month = null
553
+ let day_of_month = null
554
+ if (input && typeof input == "string") {
555
+ const items = input.split("-").map(Number)
556
+ year = parseInt(items?.[0])
557
+ month = parseInt(items?.[1])
558
+ day_of_month = parseInt(items?.[2])
559
+ }
560
+ return get_time_full_from_object({
561
+ year: year,
562
+ month: month,
563
+ day_of_month: day_of_month,
564
+ granularity: granularity,
565
+ format: format,
566
+ })
567
+ } else if (format == "year") {
568
+ return get_time_full_from_object({
569
+ year: input,
570
+ granularity: granularity,
571
+ format: format,
572
+ })
573
+ } else if (format == "year_month") {
574
+ const [year_str, month_str] = input ? input.split("-") : []
575
+ const year = year_str ? parseInt(year_str, 10) : null
576
+ const month = month_str ? parseInt(month_str, 10) : null
577
+ return get_time_full_from_object({
578
+ year: year,
579
+ month: month,
580
+ granularity: granularity,
581
+ format: format,
582
+ })
583
+ } else if (format == "hour_minute") {
584
+ const [hour_str, minute_str] = input ? input.split(":") : []
585
+ const hour = hour_str ? parseInt(hour_str, 10) : null
586
+ const minute = minute_str ? parseInt(minute_str, 10) : null
587
+ return get_time_full_from_object({
588
+ hour: hour,
589
+ minute: minute,
590
+ granularity: granularity,
591
+ format: format,
592
+ })
593
+ } else if (format == "hour_minute_second") {
594
+ const [hour_str, minute_str, second_str] = input ? input.split(":") : []
595
+ const hour = hour_str ? parseInt(hour_str, 10) : null
596
+ const minute = minute_str ? parseInt(minute_str, 10) : null
597
+ const second = second_str ? parseInt(second_str, 10) : null
598
+ return get_time_full_from_object({
599
+ hour: hour,
600
+ minute: minute,
601
+ second: second,
602
+ granularity: granularity,
603
+ format: format,
604
+ })
605
+ } else if (format == "year_week") {
606
+ const [year_str, week_of_year_str] = input ? input.split("-") : []
607
+ const year = year_str ? parseInt(year_str, 10) : null
608
+ const week_of_year = week_of_year_str ? parseInt(week_of_year_str.slice(1), 10) : null
609
+ return get_time_full_from_object({
610
+ year: year,
611
+ week_of_year: week_of_year,
612
+ granularity: granularity,
613
+ format: format,
614
+ })
615
+ } else if (format == "period_full") {
616
+ return period_full_parts_to_full(input)
617
+ } else if (format == "period_iso_8601") {
618
+ const period_full = period_iso_8601_to_period_full(input)
619
+ return period_full_parts_to_full(null, period_full)
620
+ } else if (format == "period_total_seconds") {
621
+ const period_full = total_seconds_to_period_full(input)
622
+ return period_full_parts_to_full(null, null, period_full)
623
+ }
624
+ }
625
+
626
+ export function get_val_from_time_object(input) {
627
+ if (input?.format == "period_full") {
628
+ return Number.isInteger(input?.days) ||
629
+ Number.isInteger(input?.hours) ||
630
+ Number.isInteger(input?.minutes) ||
631
+ Number.isInteger(input?.seconds)
632
+ ? {
633
+ days: Number.isInteger(input?.days) ? input?.days : null,
634
+ hours: Number.isInteger(input?.hours) ? input?.hours : null,
635
+ minutes: Number.isInteger(input?.minutes) ? input?.minutes : null,
636
+ seconds: Number.isInteger(input?.seconds) ? input?.seconds : null,
637
+ }
638
+ : null
639
+ } else if (input?.format == "period_iso_8601") {
640
+ const days = Number.isInteger(input?.days) ? input?.days : 0
641
+ const hours = Number.isInteger(input?.hours) ? input?.hours : 0
642
+ const minutes = Number.isInteger(input?.minutes) ? input?.minutes : 0
643
+ const seconds = Number.isInteger(input?.seconds) ? input?.seconds : 0
644
+ const iso8601 = `P${days > 0 ? days + "D" : ""}${hours || minutes || seconds ? "T" : ""}${
645
+ hours > 0 ? hours + "H" : ""
646
+ }${minutes > 0 ? minutes + "M" : ""}${seconds > 0 ? seconds + "S" : ""}`
647
+ return iso8601 !== "P" ? iso8601 : null
648
+ } else if (input?.format == "period_total_seconds") {
649
+ if (
650
+ !(
651
+ Number.isInteger(input?.days) ||
652
+ Number.isInteger(input?.hours) ||
653
+ Number.isInteger(input?.minutes) ||
654
+ Number.isInteger(input?.seconds)
655
+ )
656
+ ) {
657
+ return null
658
+ }
659
+ const days = Number.isInteger(input?.days) ? input?.days * 24 * 60 * 60 : 0
660
+ const hours = Number.isInteger(input?.hours) ? input?.hours * 60 * 60 : 0
661
+ const minutes = Number.isInteger(input?.minutes) ? input?.minutes * 60 : 0
662
+ const seconds = Number.isInteger(input?.seconds) ? input?.seconds : 0
663
+ const total_seconds = days + hours + minutes + seconds
664
+ return total_seconds
665
+ }
666
+ const time_full = get_time_full_from_object(input)
667
+ if (input?.format == "time_full") {
668
+ return time_full
669
+ } else if (input?.format == "epoch") {
670
+ return time_full?.epoch
671
+ } else if (input?.format == "datetime") {
672
+ return time_full?.datetime
673
+ } else if (input?.format == "datetime_utc") {
674
+ return time_full?.datetime_utc
675
+ } else if (input?.format == "datetime_zoned") {
676
+ return time_full?.datetime_zoned
677
+ } else if (input?.format == "calendar_date") {
678
+ return Number.isInteger(input?.year) && Number.isInteger(input?.month) && Number.isInteger(input?.day_of_month)
679
+ ? `${input?.year}-${input?.month.toString().padStart(2, "0")}-${input?.day_of_month.toString().padStart(2, "0")}`
680
+ : null
681
+ } else if (input?.format == "year") {
682
+ return input?.year
683
+ } else if (input?.format == "year_month") {
684
+ return Number.isInteger(input?.year) && Number.isInteger(input?.month)
685
+ ? `${input?.year}-${input?.month.toString().padStart(2, "0")}`
686
+ : null
687
+ } else if (input?.format == "year_week") {
688
+ return Number.isInteger(input?.year) && Number.isInteger(input?.week_of_year)
689
+ ? `${input?.year}-W${input?.week_of_year.toString().padStart(2, "0")}`
690
+ : null
691
+ } else if (input?.format == "hour_minute") {
692
+ return Number.isInteger(input?.hour) && Number.isInteger(input?.minute)
693
+ ? `${input?.hour.toString().padStart(2, "0")}:${input?.minute.toString().padStart(2, "0")}`
694
+ : null
695
+ } else if (input?.format == "hour_minute_second") {
696
+ return Number.isInteger(input?.hour) && Number.isInteger(input?.minute) && Number.isInteger(input?.second)
697
+ ? `${input?.hour.toString().padStart(2, "0")}:${input?.minute.toString().padStart(2, "0")}:${input?.second
698
+ .toString()
699
+ .padStart(2, "0")}`
700
+ : null
701
+ }
702
+ }