@morscherlab/mint-sdk 1.0.0-alpha.8 → 1.0.0-beta.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 +15 -15
- package/dist/{auth-BYmxZdJl.js → auth-DsI0rQ7_.js} +6 -6
- package/dist/auth-DsI0rQ7_.js.map +1 -0
- package/dist/components/index.js +2 -2
- package/dist/{components-CKf-UpGi.js → components-CzbQQPCb.js} +1429 -1429
- package/dist/components-CzbQQPCb.js.map +1 -0
- package/dist/composables/index.js +2 -2
- package/dist/composables/usePlatformContext.d.ts +3 -3
- package/dist/{composables-D0QfFzq1.js → composables-BXklV5ii.js} +3 -3
- package/dist/{composables-D0QfFzq1.js.map → composables-BXklV5ii.js.map} +1 -1
- package/dist/index.js +4 -4
- package/dist/install.d.ts +3 -3
- package/dist/install.js +5 -5
- package/dist/install.js.map +1 -1
- package/dist/stores/auth.d.ts +1 -1
- package/dist/stores/index.js +1 -1
- package/dist/stores/settings.d.ts +1 -1
- package/dist/styles.css +5388 -5388
- package/dist/types/platform.d.ts +1 -1
- package/dist/{useScheduleDrag-DAJueTbK.js → useScheduleDrag-CxBeqYcu.js} +331 -331
- package/dist/useScheduleDrag-CxBeqYcu.js.map +1 -0
- package/package.json +2 -2
- package/src/__tests__/components/AppLayout.test.ts +23 -23
- package/src/__tests__/components/AppSidebar.test.ts +29 -29
- package/src/__tests__/components/AppTopBar.test.ts +45 -45
- package/src/__tests__/components/BaseInput.test.ts +2 -2
- package/src/__tests__/components/BasePill.test.ts +37 -37
- package/src/__tests__/components/Calendar.test.ts +52 -52
- package/src/__tests__/components/CollapsibleCard.test.ts +81 -81
- package/src/__tests__/components/DataFrame.test.ts +80 -80
- package/src/__tests__/components/DropdownButton.test.ts +80 -80
- package/src/__tests__/composables/usePlatformContext.test.ts +1 -1
- package/src/components/AlertBox.story.vue +1 -1
- package/src/components/AlertBox.vue +14 -14
- package/src/components/AppAvatarMenu.vue +26 -26
- package/src/components/AppContainer.vue +3 -3
- package/src/components/AppLayout.vue +7 -7
- package/src/components/AppPageSelector.vue +30 -30
- package/src/components/AppPillNav.vue +10 -10
- package/src/components/AppPluginSwitcher.vue +31 -31
- package/src/components/AppSidebar.vue +8 -8
- package/src/components/AppTopBar.story.vue +7 -7
- package/src/components/AppTopBar.vue +102 -102
- package/src/components/AuditTrail.vue +19 -19
- package/src/components/AutoGroupModal.vue +76 -76
- package/src/components/Avatar.vue +6 -6
- package/src/components/BaseButton.vue +6 -6
- package/src/components/BaseCheckbox.vue +9 -9
- package/src/components/BaseInput.vue +4 -4
- package/src/components/BaseModal.story.vue +1 -1
- package/src/components/BaseModal.vue +14 -14
- package/src/components/BasePill.vue +9 -9
- package/src/components/BaseRadioGroup.vue +21 -21
- package/src/components/BaseSelect.vue +6 -6
- package/src/components/BaseSlider.vue +8 -8
- package/src/components/BaseTabs.vue +7 -7
- package/src/components/BaseTextarea.vue +5 -5
- package/src/components/BaseToggle.vue +10 -10
- package/src/components/BatchProgressList.vue +25 -25
- package/src/components/Breadcrumb.vue +8 -8
- package/src/components/Calendar.vue +19 -19
- package/src/components/ChartContainer.vue +9 -9
- package/src/components/ChemicalFormula.vue +7 -7
- package/src/components/CollapsibleCard.vue +20 -20
- package/src/components/ColorSlider.vue +6 -6
- package/src/components/ConcentrationInput.vue +12 -12
- package/src/components/ConfirmDialog.story.vue +1 -1
- package/src/components/ConfirmDialog.vue +7 -7
- package/src/components/DataFrame.vue +40 -40
- package/src/components/DatePicker.vue +29 -29
- package/src/components/DateTimePicker.vue +41 -41
- package/src/components/Divider.vue +9 -9
- package/src/components/DoseCalculator.vue +66 -66
- package/src/components/DropdownButton.vue +19 -19
- package/src/components/EmptyState.vue +9 -9
- package/src/components/ExperimentCodeBadge.vue +3 -3
- package/src/components/ExperimentDataViewer.vue +25 -25
- package/src/components/ExperimentPopover.vue +35 -35
- package/src/components/ExperimentSelectorModal.vue +40 -40
- package/src/components/ExperimentTimeline.vue +48 -48
- package/src/components/FileUploader.vue +31 -31
- package/src/components/FitPanel.vue +9 -9
- package/src/components/FormActions.vue +1 -1
- package/src/components/FormBuilder.vue +2 -2
- package/src/components/FormField.vue +7 -7
- package/src/components/FormSection.vue +7 -7
- package/src/components/FormulaInput.vue +10 -10
- package/src/components/GroupAssigner.vue +40 -40
- package/src/components/GroupingModal.vue +45 -45
- package/src/components/IconButton.vue +6 -6
- package/src/components/LoadingSpinner.vue +5 -5
- package/src/components/MoleculeInput.vue +21 -21
- package/src/components/MultiSelect.vue +13 -13
- package/src/components/NumberInput.vue +13 -13
- package/src/components/PlateMapEditor.vue +63 -63
- package/src/components/ProgressBar.vue +18 -18
- package/src/components/ProtocolStepEditor.vue +57 -57
- package/src/components/RackEditor.vue +28 -28
- package/src/components/ReagentEditor.vue +61 -61
- package/src/components/ReagentList.vue +49 -49
- package/src/components/ResourceCard.vue +28 -28
- package/src/components/SampleHierarchyTree.vue +13 -13
- package/src/components/SampleLegend.vue +12 -12
- package/src/components/SampleSelector.vue +104 -104
- package/src/components/ScheduleCalendar.vue +42 -42
- package/src/components/ScientificNumber.vue +11 -11
- package/src/components/SegmentedControl.vue +12 -12
- package/src/components/SequenceInput.vue +32 -32
- package/src/components/SettingsButton.vue +5 -5
- package/src/components/SettingsModal.vue +17 -17
- package/src/components/StatusIndicator.vue +5 -5
- package/src/components/StepWizard.vue +16 -16
- package/src/components/TagsInput.vue +20 -20
- package/src/components/ThemeToggle.vue +3 -3
- package/src/components/TimePicker.vue +21 -21
- package/src/components/TimeRangeInput.vue +5 -5
- package/src/components/ToastNotification.vue +8 -8
- package/src/components/Tooltip.vue +7 -7
- package/src/components/UnitInput.vue +12 -12
- package/src/components/WellEditPopup.vue +28 -28
- package/src/components/WellPlate.vue +37 -37
- package/src/composables/useAppExperiment.ts +1 -1
- package/src/composables/usePlatformContext.ts +16 -16
- package/src/composables/useProtocolTemplates.ts +1 -1
- package/src/install.ts +3 -3
- package/src/stores/auth.ts +3 -3
- package/src/stores/settings.ts +2 -2
- package/src/styles/components/alert-box.css +30 -30
- package/src/styles/components/app-avatar-menu.css +23 -23
- package/src/styles/components/app-container.css +6 -6
- package/src/styles/components/app-layout.css +15 -15
- package/src/styles/components/app-page-selector.css +26 -26
- package/src/styles/components/app-pill-nav.css +7 -7
- package/src/styles/components/app-plugin-switcher.css +27 -27
- package/src/styles/components/app-sidebar.css +24 -24
- package/src/styles/components/app-top-bar.css +65 -65
- package/src/styles/components/audit-trail.css +29 -29
- package/src/styles/components/auto-group-modal.css +91 -91
- package/src/styles/components/avatar.css +15 -15
- package/src/styles/components/batch-progress-list.css +40 -40
- package/src/styles/components/breadcrumb.css +8 -8
- package/src/styles/components/button.css +31 -31
- package/src/styles/components/calendar.css +27 -27
- package/src/styles/components/chart-container.css +9 -9
- package/src/styles/components/checkbox.css +20 -20
- package/src/styles/components/chemical-formula.css +8 -8
- package/src/styles/components/collapsible-card.css +35 -35
- package/src/styles/components/color-slider.css +8 -8
- package/src/styles/components/concentration-input.css +27 -27
- package/src/styles/components/confirm-dialog.css +32 -32
- package/src/styles/components/dataframe.css +66 -66
- package/src/styles/components/date-picker.css +40 -40
- package/src/styles/components/datetime-picker.css +37 -37
- package/src/styles/components/divider.css +13 -13
- package/src/styles/components/dose-calculator.css +43 -43
- package/src/styles/components/dropdown-button.css +46 -46
- package/src/styles/components/empty-state.css +44 -44
- package/src/styles/components/experiment-code-badge.css +8 -8
- package/src/styles/components/experiment-data-viewer.css +23 -23
- package/src/styles/components/experiment-popover.css +97 -97
- package/src/styles/components/experiment-selector-modal.css +39 -39
- package/src/styles/components/experiment-timeline.css +98 -98
- package/src/styles/components/file-uploader.css +44 -44
- package/src/styles/components/fit-panel.css +12 -12
- package/src/styles/components/form-builder.css +11 -11
- package/src/styles/components/form-field.css +7 -7
- package/src/styles/components/formula-input.css +17 -17
- package/src/styles/components/group-assigner.css +26 -26
- package/src/styles/components/grouping-modal.css +51 -51
- package/src/styles/components/icon-button.css +41 -41
- package/src/styles/components/input.css +13 -13
- package/src/styles/components/loading-spinner.css +12 -12
- package/src/styles/components/modal.css +69 -69
- package/src/styles/components/molecule-input.css +27 -27
- package/src/styles/components/multi-select.css +23 -23
- package/src/styles/components/number-input.css +32 -32
- package/src/styles/components/pill.css +37 -37
- package/src/styles/components/plate-map-editor.css +67 -67
- package/src/styles/components/progress-bar.css +41 -41
- package/src/styles/components/protocol-step-editor.css +63 -63
- package/src/styles/components/rack-editor.css +34 -34
- package/src/styles/components/radio-group.css +41 -41
- package/src/styles/components/reagent-editor.css +70 -70
- package/src/styles/components/reagent-list.css +65 -65
- package/src/styles/components/resource-card.css +52 -52
- package/src/styles/components/sample-hierarchy-tree.css +56 -56
- package/src/styles/components/sample-legend.css +37 -37
- package/src/styles/components/sample-selector.css +121 -121
- package/src/styles/components/schedule-calendar.css +67 -67
- package/src/styles/components/scientific-number.css +11 -11
- package/src/styles/components/segmented-control.css +33 -33
- package/src/styles/components/select.css +11 -11
- package/src/styles/components/sequence-input.css +29 -29
- package/src/styles/components/settings-button.css +16 -16
- package/src/styles/components/settings-modal.css +14 -14
- package/src/styles/components/skeleton.css +2 -2
- package/src/styles/components/slider.css +10 -10
- package/src/styles/components/status-indicator.css +12 -12
- package/src/styles/components/step-wizard.css +32 -32
- package/src/styles/components/tabs.css +16 -16
- package/src/styles/components/tags-input.css +46 -46
- package/src/styles/components/textarea.css +17 -17
- package/src/styles/components/theme-toggle.css +13 -13
- package/src/styles/components/time-picker.css +28 -28
- package/src/styles/components/time-range-input.css +8 -8
- package/src/styles/components/toast.css +18 -18
- package/src/styles/components/toggle.css +27 -27
- package/src/styles/components/tooltip.css +18 -18
- package/src/styles/components/unit-input.css +25 -25
- package/src/styles/components/well-edit-popup.css +32 -32
- package/src/styles/components/well-plate.css +49 -49
- package/src/styles/index.css +1 -1
- package/src/styles/variables.css +3 -3
- package/src/types/platform.ts +6 -6
- package/dist/auth-BYmxZdJl.js.map +0 -1
- package/dist/components-CKf-UpGi.js.map +0 -1
- package/dist/useScheduleDrag-DAJueTbK.js.map +0 -1
|
@@ -286,13 +286,13 @@ function getNowIndicatorStyle(): Record<string, string> | null {
|
|
|
286
286
|
}
|
|
287
287
|
|
|
288
288
|
function getStatusClass(status?: ScheduleEventStatus): string {
|
|
289
|
-
if (!status) return '
|
|
290
|
-
return `
|
|
289
|
+
if (!status) return 'mint-schedule__event--confirmed'
|
|
290
|
+
return `mint-schedule__event--${status}`
|
|
291
291
|
}
|
|
292
292
|
|
|
293
293
|
function getMonthStatusClass(status?: ScheduleEventStatus): string {
|
|
294
|
-
if (!status) return '
|
|
295
|
-
return `
|
|
294
|
+
if (!status) return 'mint-schedule__month-event--confirmed'
|
|
295
|
+
return `mint-schedule__month-event--${status}`
|
|
296
296
|
}
|
|
297
297
|
|
|
298
298
|
function onEventClick(event: ScheduleEvent, e: MouseEvent) {
|
|
@@ -361,13 +361,13 @@ onUnmounted(() => {
|
|
|
361
361
|
</script>
|
|
362
362
|
|
|
363
363
|
<template>
|
|
364
|
-
<div class="
|
|
364
|
+
<div class="mint-schedule" :style="({ '--slot-height': `${SLOT_HEIGHT}px` } as Record<string, string>)">
|
|
365
365
|
<!-- Header -->
|
|
366
|
-
<div v-if="showNavigation || showViewToggle" class="
|
|
367
|
-
<div v-if="showNavigation" class="
|
|
366
|
+
<div v-if="showNavigation || showViewToggle" class="mint-schedule__header">
|
|
367
|
+
<div v-if="showNavigation" class="mint-schedule__nav">
|
|
368
368
|
<button
|
|
369
369
|
type="button"
|
|
370
|
-
class="
|
|
370
|
+
class="mint-schedule__nav-btn"
|
|
371
371
|
aria-label="Previous"
|
|
372
372
|
@click="navigate('prev')"
|
|
373
373
|
>
|
|
@@ -377,7 +377,7 @@ onUnmounted(() => {
|
|
|
377
377
|
</button>
|
|
378
378
|
<button
|
|
379
379
|
type="button"
|
|
380
|
-
class="
|
|
380
|
+
class="mint-schedule__nav-btn"
|
|
381
381
|
aria-label="Next"
|
|
382
382
|
@click="navigate('next')"
|
|
383
383
|
>
|
|
@@ -387,21 +387,21 @@ onUnmounted(() => {
|
|
|
387
387
|
</button>
|
|
388
388
|
<button
|
|
389
389
|
type="button"
|
|
390
|
-
class="
|
|
390
|
+
class="mint-schedule__today-btn"
|
|
391
391
|
@click="navigate('today')"
|
|
392
392
|
>
|
|
393
393
|
Today
|
|
394
394
|
</button>
|
|
395
395
|
</div>
|
|
396
396
|
|
|
397
|
-
<span class="
|
|
397
|
+
<span class="mint-schedule__title">{{ headerTitle }}</span>
|
|
398
398
|
|
|
399
|
-
<div v-if="showViewToggle" class="
|
|
399
|
+
<div v-if="showViewToggle" class="mint-schedule__view-toggle">
|
|
400
400
|
<button
|
|
401
401
|
v-for="v in (['day', 'week', 'month'] as ScheduleView[])"
|
|
402
402
|
:key="v"
|
|
403
403
|
type="button"
|
|
404
|
-
:class="['
|
|
404
|
+
:class="['mint-schedule__view-btn', currentView === v ? 'mint-schedule__view-btn--active' : '']"
|
|
405
405
|
@click="setView(v)"
|
|
406
406
|
>
|
|
407
407
|
{{ v.charAt(0).toUpperCase() + v.slice(1) }}
|
|
@@ -412,18 +412,18 @@ onUnmounted(() => {
|
|
|
412
412
|
<!-- Day / Week View -->
|
|
413
413
|
<template v-if="currentView === 'day' || currentView === 'week'">
|
|
414
414
|
<!-- Day headers -->
|
|
415
|
-
<div v-if="currentView === 'week'" class="
|
|
416
|
-
<div class="
|
|
415
|
+
<div v-if="currentView === 'week'" class="mint-schedule__day-headers">
|
|
416
|
+
<div class="mint-schedule__day-header-gutter" />
|
|
417
417
|
<div
|
|
418
418
|
v-for="(day, i) in visibleDays"
|
|
419
419
|
:key="i"
|
|
420
|
-
:class="['
|
|
420
|
+
:class="['mint-schedule__day-header', isToday(day) ? 'mint-schedule__day-header--today' : '']"
|
|
421
421
|
>
|
|
422
422
|
<slot name="day-header" :date="day" :isToday="isToday(day)">
|
|
423
|
-
<span class="
|
|
423
|
+
<span class="mint-schedule__day-header-name">
|
|
424
424
|
{{ day.toLocaleDateString(locale, { weekday: 'short' }) }}
|
|
425
425
|
</span>
|
|
426
|
-
<span class="
|
|
426
|
+
<span class="mint-schedule__day-header-number">
|
|
427
427
|
{{ day.getDate() }}
|
|
428
428
|
</span>
|
|
429
429
|
</slot>
|
|
@@ -431,13 +431,13 @@ onUnmounted(() => {
|
|
|
431
431
|
</div>
|
|
432
432
|
|
|
433
433
|
<!-- Time grid body -->
|
|
434
|
-
<div ref="bodyRef" class="
|
|
434
|
+
<div ref="bodyRef" class="mint-schedule__body">
|
|
435
435
|
<!-- Time gutter -->
|
|
436
|
-
<div class="
|
|
436
|
+
<div class="mint-schedule__time-gutter">
|
|
437
437
|
<div
|
|
438
438
|
v-for="(label, i) in timeLabels"
|
|
439
439
|
:key="i"
|
|
440
|
-
class="
|
|
440
|
+
class="mint-schedule__time-label"
|
|
441
441
|
>
|
|
442
442
|
<slot name="time-label" :label="label" :index="i">
|
|
443
443
|
{{ i < timeLabels.length - 1 ? label : '' }}
|
|
@@ -446,17 +446,17 @@ onUnmounted(() => {
|
|
|
446
446
|
</div>
|
|
447
447
|
|
|
448
448
|
<!-- Day columns -->
|
|
449
|
-
<div class="
|
|
449
|
+
<div class="mint-schedule__day-columns">
|
|
450
450
|
<div
|
|
451
451
|
v-for="(day, dayIdx) in visibleDays"
|
|
452
452
|
:key="dayIdx"
|
|
453
|
-
:class="['
|
|
453
|
+
:class="['mint-schedule__day-column', isToday(day) ? 'mint-schedule__day-column--today' : '']"
|
|
454
454
|
>
|
|
455
455
|
<!-- Slot grid -->
|
|
456
456
|
<div
|
|
457
457
|
v-for="slotIdx in totalSlots"
|
|
458
458
|
:key="slotIdx"
|
|
459
|
-
:class="['
|
|
459
|
+
:class="['mint-schedule__slot', !readonly ? 'mint-schedule__slot--interactive' : '']"
|
|
460
460
|
@click="onSlotClick(day, slotIdx - 1)"
|
|
461
461
|
@pointerdown="onSlotPointerDown(day, slotIdx - 1, $event)"
|
|
462
462
|
/>
|
|
@@ -465,7 +465,7 @@ onUnmounted(() => {
|
|
|
465
465
|
<div
|
|
466
466
|
v-for="event in getEventsForDay(day)"
|
|
467
467
|
:key="event.id"
|
|
468
|
-
:class="['
|
|
468
|
+
:class="['mint-schedule__event', getStatusClass(event.status)]"
|
|
469
469
|
:style="getEventStyle(event, day) || undefined"
|
|
470
470
|
@click="onEventClick(event, $event)"
|
|
471
471
|
@pointerdown="onEventPointerDown(event, dayIdx, $event)"
|
|
@@ -473,14 +473,14 @@ onUnmounted(() => {
|
|
|
473
473
|
<slot name="event" :event="event">
|
|
474
474
|
<div
|
|
475
475
|
v-if="!readonly && event.resizable !== false"
|
|
476
|
-
class="
|
|
476
|
+
class="mint-schedule__event-resize-handle mint-schedule__event-resize-handle--top"
|
|
477
477
|
@pointerdown="onResizePointerDown(event, 'top', dayIdx, $event)"
|
|
478
478
|
/>
|
|
479
|
-
<div class="
|
|
480
|
-
<div class="
|
|
479
|
+
<div class="mint-schedule__event-title">{{ event.title }}</div>
|
|
480
|
+
<div class="mint-schedule__event-time">{{ formatEventTime(event) }}</div>
|
|
481
481
|
<div
|
|
482
482
|
v-if="!readonly && event.resizable !== false"
|
|
483
|
-
class="
|
|
483
|
+
class="mint-schedule__event-resize-handle mint-schedule__event-resize-handle--bottom"
|
|
484
484
|
@pointerdown="onResizePointerDown(event, 'bottom', dayIdx, $event)"
|
|
485
485
|
/>
|
|
486
486
|
</slot>
|
|
@@ -490,10 +490,10 @@ onUnmounted(() => {
|
|
|
490
490
|
<div
|
|
491
491
|
v-for="(blocked, bIdx) in getBlockedForDay(day)"
|
|
492
492
|
:key="`b-${bIdx}`"
|
|
493
|
-
class="
|
|
493
|
+
class="mint-schedule__blocked"
|
|
494
494
|
:style="getBlockedStyle(blocked)"
|
|
495
495
|
>
|
|
496
|
-
<span v-if="blocked.label" class="
|
|
496
|
+
<span v-if="blocked.label" class="mint-schedule__blocked-label">
|
|
497
497
|
{{ blocked.label }}
|
|
498
498
|
</span>
|
|
499
499
|
</div>
|
|
@@ -501,16 +501,16 @@ onUnmounted(() => {
|
|
|
501
501
|
<!-- Now indicator -->
|
|
502
502
|
<div
|
|
503
503
|
v-if="showNowIndicator && isToday(day) && getNowIndicatorStyle()"
|
|
504
|
-
class="
|
|
504
|
+
class="mint-schedule__now-indicator"
|
|
505
505
|
:style="getNowIndicatorStyle()!"
|
|
506
506
|
>
|
|
507
|
-
<div class="
|
|
507
|
+
<div class="mint-schedule__now-dot" />
|
|
508
508
|
</div>
|
|
509
509
|
|
|
510
510
|
<!-- Drag ghost -->
|
|
511
511
|
<div
|
|
512
512
|
v-if="isDragging && ghost && ghost.dayIndex === dayIdx"
|
|
513
|
-
class="
|
|
513
|
+
class="mint-schedule__ghost"
|
|
514
514
|
:style="ghost.style"
|
|
515
515
|
/>
|
|
516
516
|
</div>
|
|
@@ -520,12 +520,12 @@ onUnmounted(() => {
|
|
|
520
520
|
|
|
521
521
|
<!-- Month View -->
|
|
522
522
|
<template v-if="currentView === 'month'">
|
|
523
|
-
<div class="
|
|
523
|
+
<div class="mint-schedule__month-grid">
|
|
524
524
|
<!-- Weekday headers -->
|
|
525
525
|
<div
|
|
526
526
|
v-for="label in monthWeekdayLabels"
|
|
527
527
|
:key="label"
|
|
528
|
-
class="
|
|
528
|
+
class="mint-schedule__month-weekday"
|
|
529
529
|
>
|
|
530
530
|
{{ label }}
|
|
531
531
|
</div>
|
|
@@ -535,25 +535,25 @@ onUnmounted(() => {
|
|
|
535
535
|
v-for="(day, i) in monthDays"
|
|
536
536
|
:key="i"
|
|
537
537
|
:class="[
|
|
538
|
-
'
|
|
539
|
-
isToday(day.date) ? '
|
|
540
|
-
!day.isCurrentMonth ? '
|
|
538
|
+
'mint-schedule__month-cell',
|
|
539
|
+
isToday(day.date) ? 'mint-schedule__month-cell--today' : '',
|
|
540
|
+
!day.isCurrentMonth ? 'mint-schedule__month-cell--outside' : '',
|
|
541
541
|
]"
|
|
542
542
|
@click="onMonthDayClick(day.date)"
|
|
543
543
|
>
|
|
544
544
|
<slot name="month-day" :date="day.date" :isToday="isToday(day.date)" :events="getEventsForDate(day.date)">
|
|
545
|
-
<div class="
|
|
545
|
+
<div class="mint-schedule__month-date">{{ day.date.getDate() }}</div>
|
|
546
546
|
<div
|
|
547
547
|
v-for="event in getEventsForDate(day.date).slice(0, 3)"
|
|
548
548
|
:key="event.id"
|
|
549
|
-
:class="['
|
|
549
|
+
:class="['mint-schedule__month-event', getMonthStatusClass(event.status)]"
|
|
550
550
|
@click.stop="onEventClick(event, $event)"
|
|
551
551
|
>
|
|
552
552
|
{{ event.title }}
|
|
553
553
|
</div>
|
|
554
554
|
<div
|
|
555
555
|
v-if="getEventsForDate(day.date).length > 3"
|
|
556
|
-
class="
|
|
556
|
+
class="mint-schedule__month-more"
|
|
557
557
|
>
|
|
558
558
|
+{{ getEventsForDate(day.date).length - 3 }} more
|
|
559
559
|
</div>
|
|
@@ -145,38 +145,38 @@ async function copyToClipboard() {
|
|
|
145
145
|
</script>
|
|
146
146
|
|
|
147
147
|
<template>
|
|
148
|
-
<span class="
|
|
148
|
+
<span class="mint-sci-number">
|
|
149
149
|
<!-- Special values: NaN, Infinity -->
|
|
150
150
|
<template v-if="specialDisplay">
|
|
151
|
-
<span class="
|
|
151
|
+
<span class="mint-sci-number__plain">{{ specialDisplay }}</span>
|
|
152
152
|
</template>
|
|
153
153
|
|
|
154
154
|
<!-- Scientific / Engineering notation -->
|
|
155
155
|
<template v-else-if="formatted.type === 'scientific'">
|
|
156
|
-
<span class="
|
|
157
|
-
<span class="
|
|
158
|
-
<span class="
|
|
159
|
-
<span class="
|
|
156
|
+
<span class="mint-sci-number__mantissa">{{ formatted.mantissa }}</span>
|
|
157
|
+
<span class="mint-sci-number__times">×</span>
|
|
158
|
+
<span class="mint-sci-number__base">10</span>
|
|
159
|
+
<span class="mint-sci-number__exponent">{{ formatted.exponentStr }}</span>
|
|
160
160
|
</template>
|
|
161
161
|
|
|
162
162
|
<!-- Compact notation with SI suffix -->
|
|
163
163
|
<template v-else-if="formatted.type === 'compact'">
|
|
164
|
-
<span class="
|
|
165
|
-
<span v-if="formatted.suffix" class="
|
|
164
|
+
<span class="mint-sci-number__plain">{{ formatted.plain }}</span>
|
|
165
|
+
<span v-if="formatted.suffix" class="mint-sci-number__suffix">{{ formatted.suffix }}</span>
|
|
166
166
|
</template>
|
|
167
167
|
|
|
168
168
|
<!-- Plain number -->
|
|
169
169
|
<template v-else>
|
|
170
|
-
<span class="
|
|
170
|
+
<span class="mint-sci-number__plain">{{ formatted.plain }}</span>
|
|
171
171
|
</template>
|
|
172
172
|
|
|
173
173
|
<!-- Unit -->
|
|
174
|
-
<span v-if="unit" class="
|
|
174
|
+
<span v-if="unit" class="mint-sci-number__unit">{{ unit }}</span>
|
|
175
175
|
|
|
176
176
|
<!-- Copy button -->
|
|
177
177
|
<button
|
|
178
178
|
v-if="copyable"
|
|
179
|
-
:class="['
|
|
179
|
+
:class="['mint-sci-number__copy-btn', { 'mint-sci-number__copy-btn--copied': copied }]"
|
|
180
180
|
type="button"
|
|
181
181
|
:title="copied ? 'Copied!' : 'Copy value'"
|
|
182
182
|
@click.stop="copyToClipboard"
|
|
@@ -38,11 +38,11 @@ function handleKeydown(event: KeyboardEvent, option: SegmentedOption) {
|
|
|
38
38
|
<template>
|
|
39
39
|
<div
|
|
40
40
|
:class="[
|
|
41
|
-
'
|
|
42
|
-
`
|
|
43
|
-
`
|
|
44
|
-
fullWidth ? '
|
|
45
|
-
disabled ? '
|
|
41
|
+
'mint-segmented-control',
|
|
42
|
+
`mint-segmented-control--${variant}`,
|
|
43
|
+
`mint-segmented-control--${size}`,
|
|
44
|
+
fullWidth ? 'mint-segmented-control--full-width' : '',
|
|
45
|
+
disabled ? 'mint-segmented-control--disabled' : '',
|
|
46
46
|
]"
|
|
47
47
|
role="radiogroup"
|
|
48
48
|
>
|
|
@@ -54,19 +54,19 @@ function handleKeydown(event: KeyboardEvent, option: SegmentedOption) {
|
|
|
54
54
|
:aria-checked="modelValue === option.value"
|
|
55
55
|
:disabled="disabled || option.disabled"
|
|
56
56
|
:class="[
|
|
57
|
-
'
|
|
58
|
-
`
|
|
59
|
-
`
|
|
60
|
-
modelValue === option.value ? '
|
|
61
|
-
option.disabled ? '
|
|
57
|
+
'mint-segmented-control__option',
|
|
58
|
+
`mint-segmented-control__option--${variant}`,
|
|
59
|
+
`mint-segmented-control__option--${size}`,
|
|
60
|
+
modelValue === option.value ? 'mint-segmented-control__option--active' : '',
|
|
61
|
+
option.disabled ? 'mint-segmented-control__option--disabled' : '',
|
|
62
62
|
]"
|
|
63
63
|
@click="handleSelect(option)"
|
|
64
64
|
@keydown="handleKeydown($event, option)"
|
|
65
65
|
>
|
|
66
|
-
<span class="
|
|
66
|
+
<span class="mint-segmented-control__label">{{ option.label }}</span>
|
|
67
67
|
<span
|
|
68
68
|
v-if="option.description && variant === 'card'"
|
|
69
|
-
class="
|
|
69
|
+
class="mint-segmented-control__description"
|
|
70
70
|
>
|
|
71
71
|
{{ option.description }}
|
|
72
72
|
</span>
|
|
@@ -89,12 +89,12 @@ function doCopy() {
|
|
|
89
89
|
|
|
90
90
|
function getBaseClass(char: string): string {
|
|
91
91
|
const c = char.toLowerCase()
|
|
92
|
-
if (c === 'a') return '
|
|
93
|
-
if (c === 't') return '
|
|
94
|
-
if (c === 'u') return '
|
|
95
|
-
if (c === 'g') return '
|
|
96
|
-
if (c === 'c') return '
|
|
97
|
-
if (c === 'n') return '
|
|
92
|
+
if (c === 'a') return 'mint-sequence-input__base--a'
|
|
93
|
+
if (c === 't') return 'mint-sequence-input__base--t'
|
|
94
|
+
if (c === 'u') return 'mint-sequence-input__base--u'
|
|
95
|
+
if (c === 'g') return 'mint-sequence-input__base--g'
|
|
96
|
+
if (c === 'c') return 'mint-sequence-input__base--c'
|
|
97
|
+
if (c === 'n') return 'mint-sequence-input__base--n'
|
|
98
98
|
return ''
|
|
99
99
|
}
|
|
100
100
|
</script>
|
|
@@ -102,18 +102,18 @@ function getBaseClass(char: string): string {
|
|
|
102
102
|
<template>
|
|
103
103
|
<div
|
|
104
104
|
:class="[
|
|
105
|
-
'
|
|
106
|
-
error ? '
|
|
107
|
-
disabled ? '
|
|
105
|
+
'mint-sequence-input',
|
|
106
|
+
error ? 'mint-sequence-input--error' : '',
|
|
107
|
+
disabled ? 'mint-sequence-input--disabled' : '',
|
|
108
108
|
]"
|
|
109
109
|
>
|
|
110
110
|
<!-- Toolbar -->
|
|
111
|
-
<div v-if="showTools && !readonly" class="
|
|
111
|
+
<div v-if="showTools && !readonly" class="mint-sequence-input__toolbar">
|
|
112
112
|
<slot name="tools" :sequence="modelValue || ''" :type="resolvedType" :stats="stats">
|
|
113
113
|
<button
|
|
114
114
|
v-if="resolvedType !== 'protein'"
|
|
115
115
|
type="button"
|
|
116
|
-
class="
|
|
116
|
+
class="mint-sequence-input__tool-btn"
|
|
117
117
|
:disabled="!modelValue || disabled"
|
|
118
118
|
@click="doReverseComplement"
|
|
119
119
|
>
|
|
@@ -121,16 +121,16 @@ function getBaseClass(char: string): string {
|
|
|
121
121
|
</button>
|
|
122
122
|
<button
|
|
123
123
|
type="button"
|
|
124
|
-
class="
|
|
124
|
+
class="mint-sequence-input__tool-btn"
|
|
125
125
|
:disabled="!modelValue || disabled"
|
|
126
126
|
@click="doUppercase"
|
|
127
127
|
>
|
|
128
128
|
Uppercase
|
|
129
129
|
</button>
|
|
130
|
-
<div class="
|
|
130
|
+
<div class="mint-sequence-input__tool-sep" />
|
|
131
131
|
<button
|
|
132
132
|
type="button"
|
|
133
|
-
class="
|
|
133
|
+
class="mint-sequence-input__tool-btn"
|
|
134
134
|
:disabled="!modelValue || disabled"
|
|
135
135
|
@click="doCopy"
|
|
136
136
|
>
|
|
@@ -138,7 +138,7 @@ function getBaseClass(char: string): string {
|
|
|
138
138
|
</button>
|
|
139
139
|
<button
|
|
140
140
|
type="button"
|
|
141
|
-
class="
|
|
141
|
+
class="mint-sequence-input__tool-btn"
|
|
142
142
|
:disabled="!modelValue || disabled"
|
|
143
143
|
@click="doClear"
|
|
144
144
|
>
|
|
@@ -146,18 +146,18 @@ function getBaseClass(char: string): string {
|
|
|
146
146
|
</button>
|
|
147
147
|
</slot>
|
|
148
148
|
|
|
149
|
-
<span class="
|
|
149
|
+
<span class="mint-sequence-input__type-badge">{{ resolvedType }}</span>
|
|
150
150
|
</div>
|
|
151
151
|
|
|
152
152
|
<!-- Editor (input mode) -->
|
|
153
|
-
<div v-if="!readonly" class="
|
|
153
|
+
<div v-if="!readonly" class="mint-sequence-input__editor">
|
|
154
154
|
<textarea
|
|
155
155
|
:value="modelValue"
|
|
156
156
|
:rows="rows"
|
|
157
157
|
:placeholder="placeholder"
|
|
158
158
|
:disabled="disabled"
|
|
159
159
|
:maxlength="maxLength"
|
|
160
|
-
class="
|
|
160
|
+
class="mint-sequence-input__textarea"
|
|
161
161
|
spellcheck="false"
|
|
162
162
|
autocomplete="off"
|
|
163
163
|
@input="handleInput"
|
|
@@ -165,14 +165,14 @@ function getBaseClass(char: string): string {
|
|
|
165
165
|
</div>
|
|
166
166
|
|
|
167
167
|
<!-- Viewer (readonly mode) -->
|
|
168
|
-
<div v-else class="
|
|
168
|
+
<div v-else class="mint-sequence-input__viewer">
|
|
169
169
|
<div
|
|
170
170
|
v-for="(line, lineIdx) in viewerLines"
|
|
171
171
|
:key="lineIdx"
|
|
172
|
-
class="
|
|
172
|
+
class="mint-sequence-input__viewer-line"
|
|
173
173
|
>
|
|
174
|
-
<span class="
|
|
175
|
-
<span class="
|
|
174
|
+
<span class="mint-sequence-input__line-number">{{ lineIdx * 60 + 1 }}</span>
|
|
175
|
+
<span class="mint-sequence-input__line-content">
|
|
176
176
|
<span
|
|
177
177
|
v-for="(char, charIdx) in line.split('')"
|
|
178
178
|
:key="charIdx"
|
|
@@ -180,25 +180,25 @@ function getBaseClass(char: string): string {
|
|
|
180
180
|
>{{ char }}</span>
|
|
181
181
|
</span>
|
|
182
182
|
</div>
|
|
183
|
-
<div v-if="!modelValue" class="
|
|
184
|
-
<span class="
|
|
185
|
-
<span class="
|
|
183
|
+
<div v-if="!modelValue" class="mint-sequence-input__viewer-line">
|
|
184
|
+
<span class="mint-sequence-input__line-number" />
|
|
185
|
+
<span class="mint-sequence-input__line-content" style="color: var(--text-muted);">No sequence</span>
|
|
186
186
|
</div>
|
|
187
187
|
</div>
|
|
188
188
|
|
|
189
189
|
<!-- Stats -->
|
|
190
|
-
<div v-if="showStats && modelValue" class="
|
|
190
|
+
<div v-if="showStats && modelValue" class="mint-sequence-input__stats">
|
|
191
191
|
<span>
|
|
192
|
-
<span class="
|
|
193
|
-
<span class="
|
|
192
|
+
<span class="mint-sequence-input__stat-label">Length:</span>
|
|
193
|
+
<span class="mint-sequence-input__stat-value">{{ stats.length }}</span>
|
|
194
194
|
</span>
|
|
195
195
|
<span v-if="stats.gcPercent !== undefined">
|
|
196
|
-
<span class="
|
|
197
|
-
<span class="
|
|
196
|
+
<span class="mint-sequence-input__stat-label">GC:</span>
|
|
197
|
+
<span class="mint-sequence-input__stat-value">{{ stats.gcPercent.toFixed(1) }}%</span>
|
|
198
198
|
</span>
|
|
199
199
|
<span v-if="stats.molecularWeight !== undefined">
|
|
200
|
-
<span class="
|
|
201
|
-
<span class="
|
|
200
|
+
<span class="mint-sequence-input__stat-label">MW:</span>
|
|
201
|
+
<span class="mint-sequence-input__stat-value">~{{ (stats.molecularWeight / 1000).toFixed(1) }} kDa</span>
|
|
202
202
|
</span>
|
|
203
203
|
</div>
|
|
204
204
|
</div>
|
|
@@ -39,16 +39,16 @@ onUnmounted(() => {
|
|
|
39
39
|
</script>
|
|
40
40
|
|
|
41
41
|
<template>
|
|
42
|
-
<div ref="dropdownRef" class="
|
|
42
|
+
<div ref="dropdownRef" class="mint-settings-button">
|
|
43
43
|
<button
|
|
44
44
|
type="button"
|
|
45
|
-
:class="['
|
|
45
|
+
:class="['mint-settings-button__trigger', `mint-settings-button__trigger--${size}`]"
|
|
46
46
|
aria-label="Settings"
|
|
47
47
|
@click.stop="toggle"
|
|
48
48
|
>
|
|
49
49
|
<!-- Settings/Gear icon -->
|
|
50
50
|
<svg
|
|
51
|
-
:class="`
|
|
51
|
+
:class="`mint-settings-button__icon--${size}`"
|
|
52
52
|
viewBox="0 0 24 24"
|
|
53
53
|
fill="none"
|
|
54
54
|
stroke="currentColor"
|
|
@@ -61,9 +61,9 @@ onUnmounted(() => {
|
|
|
61
61
|
</button>
|
|
62
62
|
|
|
63
63
|
<!-- Dropdown panel -->
|
|
64
|
-
<div v-show="isOpen" class="
|
|
64
|
+
<div v-show="isOpen" class="mint-settings-dropdown">
|
|
65
65
|
<slot>
|
|
66
|
-
<div class="
|
|
66
|
+
<div class="mint-settings-dropdown__empty">
|
|
67
67
|
No settings configured
|
|
68
68
|
</div>
|
|
69
69
|
</slot>
|
|
@@ -61,14 +61,14 @@ function handleClose() {
|
|
|
61
61
|
@update:model-value="emit('update:modelValue', $event)"
|
|
62
62
|
@close="handleClose"
|
|
63
63
|
>
|
|
64
|
-
<div class="
|
|
64
|
+
<div class="mint-settings-modal">
|
|
65
65
|
<!-- Tabs -->
|
|
66
|
-
<div v-if="allTabs.length > 1" class="
|
|
66
|
+
<div v-if="allTabs.length > 1" class="mint-settings-modal__tabs">
|
|
67
67
|
<button
|
|
68
68
|
v-for="tab in allTabs"
|
|
69
69
|
:key="tab.id"
|
|
70
70
|
type="button"
|
|
71
|
-
:class="['
|
|
71
|
+
:class="['mint-settings-modal__tab', { 'mint-settings-modal__tab--active': activeTab === tab.id }]"
|
|
72
72
|
@click="activeTab = tab.id"
|
|
73
73
|
>
|
|
74
74
|
{{ tab.label }}
|
|
@@ -76,7 +76,7 @@ function handleClose() {
|
|
|
76
76
|
</div>
|
|
77
77
|
|
|
78
78
|
<!-- Custom tab content -->
|
|
79
|
-
<div class="
|
|
79
|
+
<div class="mint-settings-modal__content">
|
|
80
80
|
<template v-for="tab in tabs" :key="tab.id">
|
|
81
81
|
<div v-show="activeTab === tab.id">
|
|
82
82
|
<slot :name="`tab-${tab.id}`" />
|
|
@@ -86,14 +86,14 @@ function handleClose() {
|
|
|
86
86
|
<!-- Built-in appearance tab -->
|
|
87
87
|
<div v-if="showAppearance" v-show="activeTab === 'appearance'">
|
|
88
88
|
<!-- Theme -->
|
|
89
|
-
<div class="
|
|
90
|
-
<div class="
|
|
91
|
-
<div class="
|
|
89
|
+
<div class="mint-settings-modal__section">
|
|
90
|
+
<div class="mint-settings-modal__section-label">Theme</div>
|
|
91
|
+
<div class="mint-settings-modal__option-group">
|
|
92
92
|
<button
|
|
93
93
|
v-for="opt in themeOptions"
|
|
94
94
|
:key="opt.value"
|
|
95
95
|
type="button"
|
|
96
|
-
:class="['
|
|
96
|
+
:class="['mint-settings-modal__option-btn', { 'mint-settings-modal__option-btn--active': settings.theme === opt.value }]"
|
|
97
97
|
@click="settings.theme = opt.value"
|
|
98
98
|
>
|
|
99
99
|
{{ opt.label }}
|
|
@@ -102,14 +102,14 @@ function handleClose() {
|
|
|
102
102
|
</div>
|
|
103
103
|
|
|
104
104
|
<!-- Color palette -->
|
|
105
|
-
<div class="
|
|
106
|
-
<div class="
|
|
107
|
-
<div class="
|
|
105
|
+
<div class="mint-settings-modal__section">
|
|
106
|
+
<div class="mint-settings-modal__section-label">Color Palette</div>
|
|
107
|
+
<div class="mint-settings-modal__option-group">
|
|
108
108
|
<button
|
|
109
109
|
v-for="(palette, key) in colorPalettes"
|
|
110
110
|
:key="key"
|
|
111
111
|
type="button"
|
|
112
|
-
:class="['
|
|
112
|
+
:class="['mint-settings-modal__option-btn', { 'mint-settings-modal__option-btn--active': settings.colorPalette === key }]"
|
|
113
113
|
@click="settings.colorPalette = key as ColorPalette"
|
|
114
114
|
>
|
|
115
115
|
{{ palette.name }}
|
|
@@ -118,20 +118,20 @@ function handleClose() {
|
|
|
118
118
|
</div>
|
|
119
119
|
|
|
120
120
|
<!-- Table density -->
|
|
121
|
-
<div class="
|
|
122
|
-
<div class="
|
|
123
|
-
<div class="
|
|
121
|
+
<div class="mint-settings-modal__section">
|
|
122
|
+
<div class="mint-settings-modal__section-label">Table Density</div>
|
|
123
|
+
<div class="mint-settings-modal__option-group">
|
|
124
124
|
<button
|
|
125
125
|
v-for="opt in densityOptions"
|
|
126
126
|
:key="opt.value"
|
|
127
127
|
type="button"
|
|
128
|
-
:class="['
|
|
128
|
+
:class="['mint-settings-modal__option-btn', { 'mint-settings-modal__option-btn--active': settings.tableDensity === opt.value }]"
|
|
129
129
|
@click="settings.tableDensity = opt.value"
|
|
130
130
|
>
|
|
131
131
|
{{ opt.label }}
|
|
132
132
|
</button>
|
|
133
133
|
</div>
|
|
134
|
-
<p class="
|
|
134
|
+
<p class="mint-settings-modal__note">Adjusts row height in data tables.</p>
|
|
135
135
|
</div>
|
|
136
136
|
|
|
137
137
|
<slot name="appearance" />
|
|
@@ -22,16 +22,16 @@ const dotStyle = computed(() =>
|
|
|
22
22
|
</script>
|
|
23
23
|
|
|
24
24
|
<template>
|
|
25
|
-
<span class="
|
|
25
|
+
<span class="mint-status">
|
|
26
26
|
<span
|
|
27
27
|
:class="[
|
|
28
|
-
'
|
|
29
|
-
{ [`
|
|
30
|
-
{ '
|
|
28
|
+
'mint-status__dot',
|
|
29
|
+
{ [`mint-status__dot--${status}`]: !color },
|
|
30
|
+
{ 'mint-status__dot--pulse': pulse },
|
|
31
31
|
]"
|
|
32
32
|
:style="dotStyle"
|
|
33
33
|
/>
|
|
34
|
-
<span v-if="label" class="
|
|
34
|
+
<span v-if="label" class="mint-status__label">{{ label }}</span>
|
|
35
35
|
</span>
|
|
36
36
|
</template>
|
|
37
37
|
|