@mongoosejs/studio 0.5.6 → 0.5.8

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.
@@ -654,6 +654,11 @@ video {
654
654
  inset: 0px;
655
655
  }
656
656
 
657
+ .inset-x-0 {
658
+ left: 0px;
659
+ right: 0px;
660
+ }
661
+
657
662
  .inset-y-0 {
658
663
  top: 0px;
659
664
  bottom: 0px;
@@ -779,6 +784,10 @@ video {
779
784
  z-index: 50;
780
785
  }
781
786
 
787
+ .z-\[10000\] {
788
+ z-index: 10000;
789
+ }
790
+
782
791
  .z-\[10001\] {
783
792
  z-index: 10001;
784
793
  }
@@ -1025,6 +1034,10 @@ video {
1025
1034
  display: none;
1026
1035
  }
1027
1036
 
1037
+ .aspect-square {
1038
+ aspect-ratio: 1 / 1;
1039
+ }
1040
+
1028
1041
  .size-12 {
1029
1042
  width: 3rem;
1030
1043
  height: 3rem;
@@ -1112,6 +1125,10 @@ video {
1112
1125
  height: 2rem;
1113
1126
  }
1114
1127
 
1128
+ .h-9 {
1129
+ height: 2.25rem;
1130
+ }
1131
+
1115
1132
  .h-\[1\.25em\] {
1116
1133
  height: 1.25em;
1117
1134
  }
@@ -1232,10 +1249,18 @@ video {
1232
1249
  width: 2.5rem;
1233
1250
  }
1234
1251
 
1252
+ .w-11 {
1253
+ width: 2.75rem;
1254
+ }
1255
+
1235
1256
  .w-12 {
1236
1257
  width: 3rem;
1237
1258
  }
1238
1259
 
1260
+ .w-14 {
1261
+ width: 3.5rem;
1262
+ }
1263
+
1239
1264
  .w-16 {
1240
1265
  width: 4rem;
1241
1266
  }
@@ -1304,6 +1329,10 @@ video {
1304
1329
  width: 16rem;
1305
1330
  }
1306
1331
 
1332
+ .w-7 {
1333
+ width: 1.75rem;
1334
+ }
1335
+
1307
1336
  .w-8 {
1308
1337
  width: 2rem;
1309
1338
  }
@@ -1320,6 +1349,10 @@ video {
1320
1349
  width: 40%;
1321
1350
  }
1322
1351
 
1352
+ .w-\[400px\] {
1353
+ width: 400px;
1354
+ }
1355
+
1323
1356
  .w-\[60\%\] {
1324
1357
  width: 60%;
1325
1358
  }
@@ -1392,6 +1425,18 @@ video {
1392
1425
  max-width: 280px;
1393
1426
  }
1394
1427
 
1428
+ .max-w-\[400px\] {
1429
+ max-width: 400px;
1430
+ }
1431
+
1432
+ .max-w-\[420px\] {
1433
+ max-width: 420px;
1434
+ }
1435
+
1436
+ .max-w-\[calc\(100vw-2rem\)\] {
1437
+ max-width: calc(100vw - 2rem);
1438
+ }
1439
+
1395
1440
  .max-w-\[calc\(100vw-4rem\)\] {
1396
1441
  max-width: calc(100vw - 4rem);
1397
1442
  }
@@ -1563,6 +1608,18 @@ video {
1563
1608
  resize: vertical;
1564
1609
  }
1565
1610
 
1611
+ .snap-y {
1612
+ scroll-snap-type: y var(--tw-scroll-snap-strictness);
1613
+ }
1614
+
1615
+ .snap-mandatory {
1616
+ --tw-scroll-snap-strictness: mandatory;
1617
+ }
1618
+
1619
+ .snap-center {
1620
+ scroll-snap-align: center;
1621
+ }
1622
+
1566
1623
  .list-disc {
1567
1624
  list-style-type: disc;
1568
1625
  }
@@ -1581,6 +1638,10 @@ video {
1581
1638
  grid-template-columns: repeat(2, minmax(0, 1fr));
1582
1639
  }
1583
1640
 
1641
+ .grid-cols-7 {
1642
+ grid-template-columns: repeat(7, minmax(0, 1fr));
1643
+ }
1644
+
1584
1645
  .grid-cols-\[1fr_auto_1fr\] {
1585
1646
  grid-template-columns: 1fr auto 1fr;
1586
1647
  }
@@ -1665,6 +1726,10 @@ video {
1665
1726
  gap: 2rem;
1666
1727
  }
1667
1728
 
1729
+ .gap-px {
1730
+ gap: 1px;
1731
+ }
1732
+
1668
1733
  .gap-x-1 {
1669
1734
  -moz-column-gap: 0.25rem;
1670
1735
  column-gap: 0.25rem;
@@ -1782,6 +1847,10 @@ video {
1782
1847
  overflow-y: auto;
1783
1848
  }
1784
1849
 
1850
+ .overscroll-y-contain {
1851
+ overscroll-behavior-y: contain;
1852
+ }
1853
+
1785
1854
  .truncate {
1786
1855
  overflow: hidden;
1787
1856
  text-overflow: ellipsis;
@@ -1886,6 +1955,11 @@ video {
1886
1955
  border-width: 2px;
1887
1956
  }
1888
1957
 
1958
+ .border-y {
1959
+ border-top-width: 1px;
1960
+ border-bottom-width: 1px;
1961
+ }
1962
+
1889
1963
  .border-b {
1890
1964
  border-bottom-width: 1px;
1891
1965
  }
@@ -2144,6 +2218,11 @@ video {
2144
2218
  background-color: rgb(176 32 43 / var(--tw-bg-opacity));
2145
2219
  }
2146
2220
 
2221
+ .bg-merlot-800 {
2222
+ --tw-bg-opacity: 1;
2223
+ background-color: rgb(147 30 43 / var(--tw-bg-opacity));
2224
+ }
2225
+
2147
2226
  .bg-muted {
2148
2227
  background-color: var(--color-muted);
2149
2228
  }
@@ -2237,6 +2316,10 @@ video {
2237
2316
  background-color: var(--color-surface);
2238
2317
  }
2239
2318
 
2319
+ .bg-surface-hover {
2320
+ background-color: var(--color-surface-hover);
2321
+ }
2322
+
2240
2323
  .bg-teal-600 {
2241
2324
  --tw-bg-opacity: 1;
2242
2325
  background-color: rgb(0 168 165 / var(--tw-bg-opacity));
@@ -2617,6 +2700,10 @@ video {
2617
2700
  font-size: 11px;
2618
2701
  }
2619
2702
 
2703
+ .text-\[9px\] {
2704
+ font-size: 9px;
2705
+ }
2706
+
2620
2707
  .text-base {
2621
2708
  font-size: 1rem;
2622
2709
  line-height: 1.5rem;
@@ -3124,6 +3211,11 @@ video {
3124
3211
  --tw-ring-color: rgb(22 163 74 / 0.2);
3125
3212
  }
3126
3213
 
3214
+ .ring-merlot-700 {
3215
+ --tw-ring-opacity: 1;
3216
+ --tw-ring-color: rgb(176 32 43 / var(--tw-ring-opacity));
3217
+ }
3218
+
3127
3219
  .ring-red-400 {
3128
3220
  --tw-ring-opacity: 1;
3129
3221
  --tw-ring-color: rgb(248 113 113 / var(--tw-ring-opacity));
@@ -3205,6 +3297,14 @@ video {
3205
3297
  transition-timing-function: cubic-bezier(0.4, 0, 0.2, 1);
3206
3298
  }
3207
3299
 
3300
+ .\[-ms-overflow-style\:none\] {
3301
+ -ms-overflow-style: none;
3302
+ }
3303
+
3304
+ .\[scrollbar-width\:none\] {
3305
+ scrollbar-width: none;
3306
+ }
3307
+
3208
3308
  .placeholder\:text-content-tertiary::-moz-placeholder {
3209
3309
  color: var(--color-content-tertiary);
3210
3310
  }
@@ -3398,6 +3498,11 @@ video {
3398
3498
  background-color: rgb(99 102 241 / var(--tw-bg-opacity));
3399
3499
  }
3400
3500
 
3501
+ .hover\:bg-merlot-800:hover {
3502
+ --tw-bg-opacity: 1;
3503
+ background-color: rgb(147 30 43 / var(--tw-bg-opacity));
3504
+ }
3505
+
3401
3506
  .hover\:bg-muted:hover {
3402
3507
  background-color: var(--color-muted);
3403
3508
  }
@@ -3472,6 +3577,10 @@ video {
3472
3577
  background-color: rgb(100 116 139 / var(--tw-bg-opacity));
3473
3578
  }
3474
3579
 
3580
+ .hover\:bg-surface-hover:hover {
3581
+ background-color: var(--color-surface-hover);
3582
+ }
3583
+
3475
3584
  .hover\:bg-teal-500:hover {
3476
3585
  --tw-bg-opacity: 1;
3477
3586
  background-color: rgb(0 208 201 / var(--tw-bg-opacity));
@@ -4145,4 +4254,8 @@ video {
4145
4254
  :is(:where(.dark) .dark\:text-gray-500) {
4146
4255
  --tw-text-opacity: 1;
4147
4256
  color: rgb(107 114 128 / var(--tw-text-opacity));
4257
+ }
4258
+
4259
+ .\[\&\:\:-webkit-scrollbar\]\:hidden::-webkit-scrollbar {
4260
+ display: none;
4148
4261
  }
@@ -0,0 +1,155 @@
1
+ 'use strict';
2
+
3
+ function pad2(n) {
4
+ return String(n).padStart(2, '0');
5
+ }
6
+
7
+ function pad3(n) {
8
+ return String(n).padStart(3, '0');
9
+ }
10
+
11
+ /**
12
+ * @param {number} value
13
+ * @param {number} min
14
+ * @param {number} max
15
+ */
16
+ function clampInt(value, min, max) {
17
+ const n = Math.floor(Number(value));
18
+ if (Number.isNaN(n)) {
19
+ return min;
20
+ }
21
+ return Math.min(max, Math.max(min, n));
22
+ }
23
+
24
+ /**
25
+ * @param {Date} date
26
+ * @returns {string} YYYY-MM-DDTHH:mm:ss.SSS
27
+ */
28
+ function dateToDatetimeLocal(date) {
29
+ if (!(date instanceof Date) || Number.isNaN(date.getTime())) {
30
+ return '';
31
+ }
32
+ return [
33
+ date.getFullYear(),
34
+ '-',
35
+ pad2(date.getMonth() + 1),
36
+ '-',
37
+ pad2(date.getDate()),
38
+ 'T',
39
+ pad2(date.getHours()),
40
+ ':',
41
+ pad2(date.getMinutes()),
42
+ ':',
43
+ pad2(date.getSeconds()),
44
+ '.',
45
+ pad3(date.getMilliseconds())
46
+ ].join('');
47
+ }
48
+
49
+ /**
50
+ * @param {Date} date
51
+ * @returns {string} YYYY-MM-DD
52
+ */
53
+ function dateToDateOnly(date) {
54
+ if (!(date instanceof Date) || Number.isNaN(date.getTime())) {
55
+ return '';
56
+ }
57
+ return [
58
+ date.getFullYear(),
59
+ '-',
60
+ pad2(date.getMonth() + 1),
61
+ '-',
62
+ pad2(date.getDate())
63
+ ].join('');
64
+ }
65
+
66
+ /**
67
+ * @param {unknown} value
68
+ * @returns {Date|null}
69
+ */
70
+ function parseValueToDate(value) {
71
+ if (value == null || value === '') {
72
+ return null;
73
+ }
74
+ const date = new Date(value);
75
+ if (Number.isNaN(date.getTime())) {
76
+ return null;
77
+ }
78
+ return date;
79
+ }
80
+
81
+ /**
82
+ * @param {string} localValue - YYYY-MM-DD or YYYY-MM-DDTHH:mm:ss.SSS
83
+ * @returns {Date|null}
84
+ */
85
+ function localStringToDate(localValue) {
86
+ if (!localValue) {
87
+ return null;
88
+ }
89
+ const date = new Date(localValue);
90
+ if (Number.isNaN(date.getTime())) {
91
+ return null;
92
+ }
93
+ return date;
94
+ }
95
+
96
+ function isSameDay(a, b) {
97
+ if (!a || !b) {
98
+ return false;
99
+ }
100
+ return (
101
+ a.getFullYear() === b.getFullYear()
102
+ && a.getMonth() === b.getMonth()
103
+ && a.getDate() === b.getDate()
104
+ );
105
+ }
106
+
107
+ function isSameMonth(date, year, month) {
108
+ return date.getFullYear() === year && date.getMonth() === month;
109
+ }
110
+
111
+ /**
112
+ * Build a 6-row calendar grid for the given month (local timezone).
113
+ * @param {number} year
114
+ * @param {number} month - 0-indexed
115
+ * @returns {Array<{ key: string, label: number, date: Date, inMonth: boolean }>}
116
+ */
117
+ function buildCalendarDays(year, month) {
118
+ const firstOfMonth = new Date(year, month, 1);
119
+ const startOffset = firstOfMonth.getDay();
120
+ const gridStart = new Date(year, month, 1 - startOffset);
121
+
122
+ const days = [];
123
+ for (let i = 0; i < 42; i++) {
124
+ const date = new Date(gridStart.getFullYear(), gridStart.getMonth(), gridStart.getDate() + i);
125
+ days.push({
126
+ key: `${date.getFullYear()}-${pad2(date.getMonth() + 1)}-${pad2(date.getDate())}`,
127
+ label: date.getDate(),
128
+ date,
129
+ inMonth: date.getMonth() === month
130
+ });
131
+ }
132
+ return days;
133
+ }
134
+
135
+ const WEEKDAY_LABELS = ['Su', 'Mo', 'Tu', 'We', 'Th', 'Fr', 'Sa'];
136
+
137
+ const MONTH_LABELS = [
138
+ 'January', 'February', 'March', 'April', 'May', 'June',
139
+ 'July', 'August', 'September', 'October', 'November', 'December'
140
+ ];
141
+
142
+ module.exports = {
143
+ pad2,
144
+ pad3,
145
+ clampInt,
146
+ dateToDatetimeLocal,
147
+ dateToDateOnly,
148
+ parseValueToDate,
149
+ localStringToDate,
150
+ isSameDay,
151
+ isSameMonth,
152
+ buildCalendarDays,
153
+ WEEKDAY_LABELS,
154
+ MONTH_LABELS
155
+ };
@@ -1,5 +1,7 @@
1
1
  'use strict';
2
2
 
3
+ const { dateToDatetimeLocal } = require('./calendar');
4
+
3
5
  const { Trie } = require('../models/trie');
4
6
 
5
7
  const QUERY_SELECTORS = [
@@ -49,7 +51,7 @@ function buildAutocompleteTrie(schemaPaths) {
49
51
  trie.bulkInsert(QUERY_SELECTORS, 5, 'operator');
50
52
  trie.bulkInsert(QUERY_SELECTORS, 5, 'fieldName');
51
53
  trie.bulkInsert(VALUE_HELPERS, 5, 'value');
52
-
54
+
53
55
  if (Array.isArray(schemaPaths) && schemaPaths.length > 0) {
54
56
  const paths = schemaPaths
55
57
  .map(path => path?.path)
@@ -61,13 +63,13 @@ function buildAutocompleteTrie(schemaPaths) {
61
63
  }
62
64
  trie.bulkInsert(paths, 10, 'fieldName');
63
65
  }
64
-
66
+
65
67
  return trie;
66
68
  }
67
69
 
68
70
  function getAutocompleteContext(searchText, cursorPos) {
69
71
  const before = searchText.slice(0, cursorPos);
70
-
72
+
71
73
  // Check if we're in a field name context (after { or ,)
72
74
  // This takes precedence over value context to handle cases like { _id: { $gt
73
75
  const fieldMatch = before.match(/(?:\{|,)\s*([^:\s]*)$/);
@@ -79,7 +81,7 @@ function getAutocompleteContext(searchText, cursorPos) {
79
81
  startPos: cursorPos - token.length
80
82
  };
81
83
  }
82
-
84
+
83
85
  // Check if we're in a value context (after a colon)
84
86
  // Match the last colon followed by optional whitespace and capture everything after
85
87
  const valueMatch = before.match(/:\s*(\{?\s*)([^\s,\}\]:]*)$/);
@@ -91,19 +93,19 @@ function getAutocompleteContext(searchText, cursorPos) {
91
93
  startPos: cursorPos - token.length
92
94
  };
93
95
  }
94
-
96
+
95
97
  return null;
96
98
  }
97
99
 
98
100
  function getAutocompleteSuggestions(trie, searchText, cursorPos, schemaPaths) {
99
101
  const context = getAutocompleteContext(searchText, cursorPos);
100
-
102
+
101
103
  if (!context) {
102
104
  return [];
103
105
  }
104
-
106
+
105
107
  const { token, role } = context;
106
-
108
+
107
109
  // Extract the actual term without quotes
108
110
  const leadingQuoteMatch = token.match(/^["']/);
109
111
  const trailingQuoteMatch = token.length > 1 && /["']$/.test(token)
@@ -113,14 +115,14 @@ function getAutocompleteSuggestions(trie, searchText, cursorPos, schemaPaths) {
113
115
  .replace(/^["']/, '')
114
116
  .replace(trailingQuoteMatch ? new RegExp(`[${trailingQuoteMatch}]$`) : '', '')
115
117
  .trim();
116
-
118
+
117
119
  if (!term) {
118
120
  return [];
119
121
  }
120
-
122
+
121
123
  const primarySuggestions = trie.getSuggestions(term, 10, role);
122
124
  const suggestionsSet = new Set(primarySuggestions);
123
-
125
+
124
126
  // Add schema path suggestions for field names
125
127
  if (role === 'fieldName' && Array.isArray(schemaPaths) && schemaPaths.length > 0) {
126
128
  for (const schemaPath of schemaPaths) {
@@ -137,9 +139,9 @@ function getAutocompleteSuggestions(trie, searchText, cursorPos, schemaPaths) {
137
139
  }
138
140
  }
139
141
  }
140
-
142
+
141
143
  let suggestions = Array.from(suggestionsSet);
142
-
144
+
143
145
  // Preserve quotes if present
144
146
  if (leadingQuoteMatch) {
145
147
  const leadingQuote = leadingQuoteMatch[0];
@@ -150,14 +152,14 @@ function getAutocompleteSuggestions(trie, searchText, cursorPos, schemaPaths) {
150
152
  suggestion.endsWith(trailingQuoteMatch) ? suggestion : `${suggestion}${trailingQuoteMatch}`
151
153
  );
152
154
  }
153
-
155
+
154
156
  return suggestions;
155
157
  }
156
158
 
157
159
  function applySuggestion(searchText, cursorPos, suggestion) {
158
160
  const before = searchText.slice(0, cursorPos);
159
161
  const after = searchText.slice(cursorPos);
160
-
162
+
161
163
  // Check if we're in a value context
162
164
  const valueMatch = before.match(/:\s*(\{?\s*)([^\s,\}\]:]*)$/);
163
165
  if (valueMatch) {
@@ -165,30 +167,30 @@ function applySuggestion(searchText, cursorPos, suggestion) {
165
167
  const start = cursorPos - token.length;
166
168
  let replacement = suggestion;
167
169
  let cursorOffset = replacement.length;
168
-
170
+
169
171
  // Add parentheses for function helpers and position cursor inside
170
172
  if (FUNCTION_HELPERS.has(suggestion)) {
171
173
  replacement = `${suggestion}()`;
172
174
  cursorOffset = suggestion.length + 1; // Position cursor between ()
173
175
  }
174
-
176
+
175
177
  return {
176
178
  text: searchText.slice(0, start) + replacement + after,
177
179
  newCursorPos: start + cursorOffset
178
180
  };
179
181
  }
180
-
182
+
181
183
  // Check if we're in a field name context
182
184
  const fieldMatch = before.match(/(?:\{|,)\s*([^:\s]*)$/);
183
185
  if (fieldMatch) {
184
186
  const token = fieldMatch[1];
185
187
  const start = cursorPos - token.length;
186
188
  let replacement = suggestion;
187
-
189
+
188
190
  const leadingQuote = token.startsWith('"') || token.startsWith('\'') ? token[0] : '';
189
191
  const trailingQuote = token.length > 1 && (token.endsWith('"') || token.endsWith('\'')) ? token[token.length - 1] : '';
190
192
  const colonNeeded = !/^\s*:/.test(after);
191
-
193
+
192
194
  // If suggestion already has quotes, use it as-is
193
195
  const suggestionHasQuotes = (suggestion.startsWith('"') || suggestion.startsWith('\'')) &&
194
196
  (suggestion.endsWith('"') || suggestion.endsWith('\''));
@@ -202,27 +204,107 @@ function applySuggestion(searchText, cursorPos, suggestion) {
202
204
  replacement = `${replacement}${trailingQuote}`;
203
205
  }
204
206
  }
205
-
207
+
206
208
  // Only insert : if we know the user isn't entering in a nested path
207
209
  // If suggestion has full quotes or user typed both quotes, add colon
208
210
  if (colonNeeded && (suggestionHasQuotes || !leadingQuote || trailingQuote)) {
209
211
  replacement = `${replacement}:`;
210
212
  }
211
-
213
+
212
214
  return {
213
215
  text: searchText.slice(0, start) + replacement + after,
214
216
  newCursorPos: start + replacement.length
215
217
  };
216
218
  }
217
-
219
+
218
220
  return null;
219
221
  }
220
222
 
223
+ /**
224
+ * When the cursor is inside a Date(…) or new Date(…) argument, returns the
225
+ * slice indices of that argument so a picker can replace it with a quoted ISO string.
226
+ */
227
+ function getDatePickerInsertionRange(searchText, cursorPos) {
228
+ const before = searchText.slice(0, cursorPos);
229
+ const re = /((?:new\s+)?Date\s*\(\s*)([^)]*)$/i;
230
+ const m = before.match(re);
231
+ if (!m) {
232
+ return null;
233
+ }
234
+ const innerStart = m.index + m[1].length;
235
+ const after = searchText.slice(cursorPos);
236
+ let closeIdx = -1;
237
+ let parenDepth = 0;
238
+ for (let k = 0; k < after.length; k++) {
239
+ const ch = after[k];
240
+ if (ch === '(') {
241
+ parenDepth++;
242
+ } else if (ch === ')') {
243
+ if (parenDepth === 0) {
244
+ closeIdx = cursorPos + k;
245
+ break;
246
+ }
247
+ parenDepth--;
248
+ }
249
+ }
250
+ const innerEnd = closeIdx >= 0 ? closeIdx : cursorPos;
251
+ const needsClosingParen = closeIdx < 0;
252
+ return { innerStart, innerEnd, needsClosingParen };
253
+ }
254
+
255
+ function dateArgumentSliceToDatetimeLocal(slice) {
256
+ const t = slice.trim();
257
+ if (!t) {
258
+ return '';
259
+ }
260
+ const unquoted = (t.startsWith('"') && t.endsWith('"')) || (t.startsWith('\'') && t.endsWith('\''))
261
+ ? t.slice(1, -1)
262
+ : t;
263
+ const d = new Date(unquoted);
264
+ if (Number.isNaN(d.getTime())) {
265
+ return '';
266
+ }
267
+ return dateToDatetimeLocal(d);
268
+ }
269
+
270
+ /**
271
+ * @param {Date} date
272
+ * @param {'quoted'|'timestamp'} format
273
+ */
274
+ function formatDateArgumentValue(date, format) {
275
+ if (format === 'quoted') {
276
+ return JSON.stringify(date.toISOString());
277
+ }
278
+ return String(date.getTime());
279
+ }
280
+
281
+ /**
282
+ * Inserts a Date argument value as timestamp or quoted ISO string.
283
+ * @param {string} searchText
284
+ * @param {{ innerStart: number, innerEnd: number, needsClosingParen?: boolean }} range
285
+ * @param {Date} date
286
+ * @param {'quoted'|'timestamp'} [format] - when omitted, inferred from the existing argument
287
+ */
288
+ function insertDateInDateArgument(searchText, range, date, format) {
289
+ const slice = searchText.slice(range.innerStart, range.innerEnd);
290
+ const insertion = formatDateArgumentValue(date, format);
291
+ const { innerStart, innerEnd } = range;
292
+ const closing = range.needsClosingParen === true ? ')' : '';
293
+ return {
294
+ text: searchText.slice(0, innerStart) + insertion + closing + searchText.slice(innerEnd),
295
+ newCursorPos: innerStart + insertion.length + closing.length
296
+ };
297
+ }
298
+
221
299
  module.exports = {
222
300
  buildAutocompleteTrie,
223
301
  getAutocompleteContext,
224
302
  getAutocompleteSuggestions,
225
303
  applySuggestion,
304
+ getDatePickerInsertionRange,
305
+ dateArgumentSliceToDatetimeLocal,
306
+ formatDateArgumentValue,
307
+ insertDateInDateArgument,
226
308
  QUERY_SELECTORS,
227
309
  VALUE_HELPERS,
228
310
  FUNCTION_HELPERS