@visns-studio/visns-components 6.16.6 → 6.17.1
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.
- package/README.md +148 -3
- package/package.json +1 -1
- package/src/components/sms/SmsClientConversations.jsx +439 -0
- package/src/components/sms/SmsComposeModal.jsx +37 -3
- package/src/components/sms/SmsInbox.jsx +43 -80
- package/src/components/sms/smsHelpers.js +111 -0
- package/src/components/sms/useSmsThreads.js +211 -0
- package/src/components/styles/Sms.module.scss +167 -0
- package/src/components/styles/global.css +33 -1
- package/src/index.js +12 -0
|
@@ -2386,3 +2386,170 @@ $sms-mono: 'SFMono-Regular', 'Menlo', 'Consolas', monospace;
|
|
|
2386
2386
|
grid-template-columns: 1fr;
|
|
2387
2387
|
}
|
|
2388
2388
|
}
|
|
2389
|
+
|
|
2390
|
+
// ---------------------------------------------------------------------------
|
|
2391
|
+
// SmsClientConversations — one client's messages, as a card on their page
|
|
2392
|
+
// ---------------------------------------------------------------------------
|
|
2393
|
+
// A card rather than a page: it mounts inside a client's tab strip, beside
|
|
2394
|
+
// other cards, and has to be a self-contained box with its own height. The
|
|
2395
|
+
// panes inside it are the inbox's, with the rail narrowed — every row is the
|
|
2396
|
+
// same person, so it carries a line and a number rather than a name and an
|
|
2397
|
+
// avatar.
|
|
2398
|
+
|
|
2399
|
+
.clientCard {
|
|
2400
|
+
@include sms-tokens;
|
|
2401
|
+
|
|
2402
|
+
display: flex;
|
|
2403
|
+
flex-direction: column;
|
|
2404
|
+
gap: 0.65rem;
|
|
2405
|
+
box-sizing: border-box;
|
|
2406
|
+
color: var(--s-paragraph);
|
|
2407
|
+
font-size: 0.85rem;
|
|
2408
|
+
}
|
|
2409
|
+
|
|
2410
|
+
.clientCardHead {
|
|
2411
|
+
display: flex;
|
|
2412
|
+
flex-wrap: wrap;
|
|
2413
|
+
gap: 0.6rem 1rem;
|
|
2414
|
+
align-items: center;
|
|
2415
|
+
justify-content: space-between;
|
|
2416
|
+
}
|
|
2417
|
+
|
|
2418
|
+
.clientCardHeading {
|
|
2419
|
+
display: flex;
|
|
2420
|
+
flex-direction: column;
|
|
2421
|
+
gap: 0.1rem;
|
|
2422
|
+
min-width: 0;
|
|
2423
|
+
}
|
|
2424
|
+
|
|
2425
|
+
.clientCardTitle {
|
|
2426
|
+
display: flex;
|
|
2427
|
+
gap: 0.45rem;
|
|
2428
|
+
align-items: center;
|
|
2429
|
+
margin: 0;
|
|
2430
|
+
color: var(--s-paragraph);
|
|
2431
|
+
font-size: 1rem;
|
|
2432
|
+
font-weight: 700;
|
|
2433
|
+
line-height: 1.3;
|
|
2434
|
+
|
|
2435
|
+
svg {
|
|
2436
|
+
flex-shrink: 0;
|
|
2437
|
+
color: var(--s-primary);
|
|
2438
|
+
}
|
|
2439
|
+
}
|
|
2440
|
+
|
|
2441
|
+
.clientCardMeta {
|
|
2442
|
+
margin: 0;
|
|
2443
|
+
color: var(--s-muted);
|
|
2444
|
+
font-size: 0.78rem;
|
|
2445
|
+
}
|
|
2446
|
+
|
|
2447
|
+
.clientCardActions {
|
|
2448
|
+
display: flex;
|
|
2449
|
+
flex-wrap: wrap;
|
|
2450
|
+
gap: 0.4rem;
|
|
2451
|
+
align-items: center;
|
|
2452
|
+
margin-left: auto;
|
|
2453
|
+
|
|
2454
|
+
// "Open in Messages" is a real anchor so it can be middle-clicked and
|
|
2455
|
+
// copied; the ghost-button rules are written for `button`, so the box has
|
|
2456
|
+
// to be restated for an `a`.
|
|
2457
|
+
.ghostButton {
|
|
2458
|
+
display: inline-flex;
|
|
2459
|
+
align-items: center;
|
|
2460
|
+
text-decoration: none;
|
|
2461
|
+
}
|
|
2462
|
+
}
|
|
2463
|
+
|
|
2464
|
+
.clientCardBody {
|
|
2465
|
+
box-sizing: border-box;
|
|
2466
|
+
border: 1px solid var(--s-line);
|
|
2467
|
+
border-radius: var(--s-br);
|
|
2468
|
+
background: var(--s-background);
|
|
2469
|
+
}
|
|
2470
|
+
|
|
2471
|
+
// Nothing to show, and nothing wrong: most clients have never been texted, so
|
|
2472
|
+
// this is the state the card is usually in and it has to look deliberate.
|
|
2473
|
+
.clientEmpty {
|
|
2474
|
+
display: flex;
|
|
2475
|
+
flex-direction: column;
|
|
2476
|
+
gap: 0.7rem;
|
|
2477
|
+
align-items: center;
|
|
2478
|
+
justify-content: center;
|
|
2479
|
+
padding: 2rem 1rem;
|
|
2480
|
+
text-align: center;
|
|
2481
|
+
|
|
2482
|
+
p {
|
|
2483
|
+
margin: 0;
|
|
2484
|
+
color: var(--s-muted);
|
|
2485
|
+
font-size: 0.85rem;
|
|
2486
|
+
}
|
|
2487
|
+
}
|
|
2488
|
+
|
|
2489
|
+
.clientPanes {
|
|
2490
|
+
// The height is the `height` prop, set inline. The page-sized default and
|
|
2491
|
+
// the 420px floor both belong to the full inbox, and a card that ignored a
|
|
2492
|
+
// 320px request would be the prop not working.
|
|
2493
|
+
height: auto;
|
|
2494
|
+
min-height: 0;
|
|
2495
|
+
grid-template-columns: 236px minmax(0, 1fr);
|
|
2496
|
+
}
|
|
2497
|
+
|
|
2498
|
+
.clientRail {
|
|
2499
|
+
// The rail is short by nature — one conversation, occasionally three — so
|
|
2500
|
+
// it does not need the inbox's paging furniture, only its scroll.
|
|
2501
|
+
flex: 1;
|
|
2502
|
+
}
|
|
2503
|
+
|
|
2504
|
+
// No avatar track: every row is the same person, and a column of identical
|
|
2505
|
+
// initials is a column of nothing.
|
|
2506
|
+
.clientRow {
|
|
2507
|
+
grid-template-columns: 3px minmax(0, 1fr);
|
|
2508
|
+
padding-right: 0.6rem;
|
|
2509
|
+
}
|
|
2510
|
+
|
|
2511
|
+
.clientRowNumber {
|
|
2512
|
+
display: block;
|
|
2513
|
+
overflow: hidden;
|
|
2514
|
+
margin-top: 0.05rem;
|
|
2515
|
+
color: var(--s-muted);
|
|
2516
|
+
font-size: 0.74rem;
|
|
2517
|
+
font-variant-numeric: tabular-nums;
|
|
2518
|
+
text-overflow: ellipsis;
|
|
2519
|
+
white-space: nowrap;
|
|
2520
|
+
}
|
|
2521
|
+
|
|
2522
|
+
// Narrow: the rail stops being a column and becomes a strip above the
|
|
2523
|
+
// conversation. Same rows, scrolled sideways — a client tab is often half a
|
|
2524
|
+
// screen wide, and 236px of that is most of it.
|
|
2525
|
+
@media (max-width: 780px) {
|
|
2526
|
+
.clientPanes {
|
|
2527
|
+
grid-template-rows: auto minmax(0, 1fr);
|
|
2528
|
+
grid-template-columns: minmax(0, 1fr);
|
|
2529
|
+
}
|
|
2530
|
+
|
|
2531
|
+
.clientPanes .listPane {
|
|
2532
|
+
border-right: none;
|
|
2533
|
+
border-bottom: 1px solid var(--s-line);
|
|
2534
|
+
}
|
|
2535
|
+
|
|
2536
|
+
.clientRail {
|
|
2537
|
+
display: flex;
|
|
2538
|
+
gap: 0.4rem;
|
|
2539
|
+
padding: 0.4rem;
|
|
2540
|
+
overflow-x: auto;
|
|
2541
|
+
overflow-y: hidden;
|
|
2542
|
+
|
|
2543
|
+
> li {
|
|
2544
|
+
flex: 0 0 auto;
|
|
2545
|
+
width: 220px;
|
|
2546
|
+
}
|
|
2547
|
+
}
|
|
2548
|
+
|
|
2549
|
+
.clientRow {
|
|
2550
|
+
height: 100%;
|
|
2551
|
+
padding: 0.45rem 0.6rem 0.45rem 0;
|
|
2552
|
+
border-bottom: none;
|
|
2553
|
+
border-radius: var(--s-br);
|
|
2554
|
+
}
|
|
2555
|
+
}
|
|
@@ -247,7 +247,9 @@ input[type]:not([type='search']):not([type='url']):not([type='hidden']):not(
|
|
|
247
247
|
.variable-inserter-search-input
|
|
248
248
|
):not(.react-datepicker__month-select):not(
|
|
249
249
|
.react-datepicker__year-select
|
|
250
|
-
):not(.visns-native-date-filter__input)
|
|
250
|
+
):not(.visns-native-date-filter__input):not([type='date']):not(
|
|
251
|
+
[type='datetime-local']
|
|
252
|
+
):not([type='time']) {
|
|
251
253
|
background: white;
|
|
252
254
|
border-radius: var(--br);
|
|
253
255
|
border: 1px solid rgba(var(--paragraph-color-rgb), 0.15);
|
|
@@ -266,6 +268,36 @@ input[type]:not([type='search']):not([type='url']):not([type='hidden']):not(
|
|
|
266
268
|
}
|
|
267
269
|
}
|
|
268
270
|
|
|
271
|
+
/* Native date / time inputs are excluded from the padded rule above: 1rem of
|
|
272
|
+
padding inside a date control made it ~48px and, in Firefox, sat the value
|
|
273
|
+
low. They get a flat 34px control instead, matching the grid filters. */
|
|
274
|
+
input[type='date'],
|
|
275
|
+
input[type='datetime-local'],
|
|
276
|
+
input[type='time'] {
|
|
277
|
+
box-sizing: border-box;
|
|
278
|
+
height: 34px;
|
|
279
|
+
min-height: 34px;
|
|
280
|
+
padding: 0 10px;
|
|
281
|
+
border: 1px solid rgba(var(--paragraph-color-rgb, 31, 31, 31), 0.15);
|
|
282
|
+
border-radius: var(--br, 4px);
|
|
283
|
+
background: #fff;
|
|
284
|
+
color: var(--paragraph-color, #1f1f1f);
|
|
285
|
+
font-family: inherit;
|
|
286
|
+
font-size: 0.85rem;
|
|
287
|
+
line-height: 32px;
|
|
288
|
+
font-variant-numeric: tabular-nums;
|
|
289
|
+
}
|
|
290
|
+
|
|
291
|
+
@-moz-document url-prefix() {
|
|
292
|
+
input[type='date'],
|
|
293
|
+
input[type='datetime-local'],
|
|
294
|
+
input[type='time'] {
|
|
295
|
+
height: 34px;
|
|
296
|
+
padding: 0 8px;
|
|
297
|
+
line-height: 32px;
|
|
298
|
+
}
|
|
299
|
+
}
|
|
300
|
+
|
|
269
301
|
.popup-content {
|
|
270
302
|
border-radius: var(--br);
|
|
271
303
|
padding: 0 !important;
|
package/src/index.js
CHANGED
|
@@ -143,12 +143,14 @@ import {
|
|
|
143
143
|
// Messaging — the SMS inbox. SmsInboxBadge mounts through Navigation's
|
|
144
144
|
// `renderers` slot; SmsInbox is the page behind it, SmsThreadPanel is the
|
|
145
145
|
// conversation on its own for embedding elsewhere.
|
|
146
|
+
import SmsClientConversations from './components/sms/SmsClientConversations';
|
|
146
147
|
import SmsComposeModal from './components/sms/SmsComposeModal';
|
|
147
148
|
import SmsInbox from './components/sms/SmsInbox';
|
|
148
149
|
import SmsInboxBadge from './components/sms/SmsInboxBadge';
|
|
149
150
|
import SmsLineSettings from './components/sms/SmsLineSettings';
|
|
150
151
|
import SmsThreadPanel from './components/sms/SmsThreadPanel';
|
|
151
152
|
import useSmsLive from './components/sms/useSmsLive';
|
|
153
|
+
import useSmsThreads from './components/sms/useSmsThreads';
|
|
152
154
|
import {
|
|
153
155
|
DEFAULT_ENDPOINTS as DEFAULT_SMS_ENDPOINTS,
|
|
154
156
|
makeSmsEndpoints,
|
|
@@ -158,6 +160,8 @@ import {
|
|
|
158
160
|
MAX_SEGMENTS as SMS_MAX_SEGMENTS,
|
|
159
161
|
SMS_LIMITS,
|
|
160
162
|
STATUS_LABELS as SMS_STATUS_LABELS,
|
|
163
|
+
clientRecipient,
|
|
164
|
+
conversationCountLabel,
|
|
161
165
|
describeTransport,
|
|
162
166
|
fillTemplate,
|
|
163
167
|
groupMessagesByDay,
|
|
@@ -166,6 +170,8 @@ import {
|
|
|
166
170
|
looksLikeNumber,
|
|
167
171
|
nextPlaceholder,
|
|
168
172
|
normaliseNumberForDisplay,
|
|
173
|
+
orderThreadsByRecency,
|
|
174
|
+
pickInitialThread,
|
|
169
175
|
relativeTime,
|
|
170
176
|
segmentCount,
|
|
171
177
|
splitPersonName,
|
|
@@ -277,6 +283,8 @@ export {
|
|
|
277
283
|
VaultEntryForm,
|
|
278
284
|
VaultManager,
|
|
279
285
|
VaultQuickSearch,
|
|
286
|
+
clientRecipient,
|
|
287
|
+
conversationCountLabel,
|
|
280
288
|
DEFAULT_SMS_ENDPOINTS,
|
|
281
289
|
describeTransport,
|
|
282
290
|
fillTemplate,
|
|
@@ -287,6 +295,8 @@ export {
|
|
|
287
295
|
makeSmsEndpoints,
|
|
288
296
|
nextPlaceholder,
|
|
289
297
|
normaliseNumberForDisplay,
|
|
298
|
+
orderThreadsByRecency,
|
|
299
|
+
pickInitialThread,
|
|
290
300
|
relativeTime,
|
|
291
301
|
resolveSmsEndpoints,
|
|
292
302
|
segmentCount,
|
|
@@ -294,6 +304,7 @@ export {
|
|
|
294
304
|
SMS_LIMITS,
|
|
295
305
|
SMS_MAX_SEGMENTS,
|
|
296
306
|
SMS_STATUS_LABELS,
|
|
307
|
+
SmsClientConversations,
|
|
297
308
|
SmsComposeModal,
|
|
298
309
|
SmsInbox,
|
|
299
310
|
SmsInboxBadge,
|
|
@@ -302,6 +313,7 @@ export {
|
|
|
302
313
|
threadDisplayName,
|
|
303
314
|
toE164,
|
|
304
315
|
useSmsLive,
|
|
316
|
+
useSmsThreads,
|
|
305
317
|
CameraPlacement,
|
|
306
318
|
CellWithTooltip,
|
|
307
319
|
clampOtp,
|