@hanology/cham-browser 0.4.17 → 0.4.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.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@hanology/cham-browser",
3
- "version": "0.4.17",
3
+ "version": "0.4.18",
4
4
  "description": "CHAM — browser-compatible parser, serializer, and site generator for Classical Han Annotated Markdown",
5
5
  "type": "module",
6
6
  "main": "dist/index.js",
@@ -11,6 +11,7 @@ const props = defineProps<{
11
11
  headwords: Record<string, string>
12
12
  layerLabels?: Record<string, string>
13
13
  activeId: string
14
+ vertical?: boolean
14
15
  }>()
15
16
 
16
17
  const emit = defineEmits<{
@@ -75,7 +76,7 @@ onBeforeUnmount(() => document.removeEventListener('keydown', onKeydown))
75
76
  <template>
76
77
  <Teleport to="body">
77
78
  <Transition name="ann-pane">
78
- <div v-if="visible && annotations.length" class="ann-pane">
79
+ <div v-if="visible && annotations.length" class="ann-pane" :class="{ vertical }">
79
80
  <div class="ann-pane-header">
80
81
  <span class="ann-pane-title">注釋</span>
81
82
  <span class="ann-pane-count">{{ annotations.length }}</span>
@@ -305,4 +306,41 @@ onBeforeUnmount(() => document.removeEventListener('keydown', onKeydown))
305
306
  transform: translateY(100%);
306
307
  }
307
308
  }
309
+
310
+ /* ─── Vertical mode ─── */
311
+ .ann-pane.vertical {
312
+ writing-mode: vertical-rl;
313
+ text-orientation: mixed;
314
+ width: 240px;
315
+ }
316
+
317
+ .ann-pane.vertical .ann-pane-body {
318
+ overflow-x: auto;
319
+ overflow-y: hidden;
320
+ }
321
+
322
+ .ann-pane.vertical .ann-pane-entry {
323
+ padding: 12px 8px;
324
+ border-bottom: none;
325
+ border-left: 1px solid var(--border-light);
326
+ border-right: 3px solid transparent;
327
+ }
328
+
329
+ .ann-pane.vertical .ann-pane-entry.active {
330
+ border-right-color: var(--vermillion);
331
+ }
332
+
333
+ .ann-pane.vertical .ann-pane-entry.active.pronunciation {
334
+ border-right-color: var(--jade);
335
+ }
336
+
337
+ .ann-pane.vertical .ann-pane-entry-head {
338
+ flex-direction: column;
339
+ gap: 4px;
340
+ }
341
+
342
+ .ann-pane.vertical .ann-pane-text {
343
+ line-height: 2;
344
+ letter-spacing: 1px;
345
+ }
308
346
  </style>
@@ -118,6 +118,7 @@ onBeforeUnmount(() => {
118
118
  <div
119
119
  v-if="!isMobile && stickyVisible && annotations.length"
120
120
  class="ann-card"
121
+ :class="{ vertical }"
121
122
  :style="style"
122
123
  @mouseenter="emit('tooltipEnter')"
123
124
  @mouseleave="emit('tooltipLeave')"
@@ -136,7 +137,7 @@ onBeforeUnmount(() => {
136
137
  <span v-if="layerLabel(ann)" class="ann-layer">{{ layerLabel(ann) }}</span>
137
138
  </div>
138
139
  <div class="ann-entry-body">
139
- <PronunciationGroup v-if="getSegment(ann)" :segment="getSegment(ann)!" />
140
+ <div v-if="getSegment(ann)" class="ann-pron-h"><PronunciationGroup :segment="getSegment(ann)!" /></div>
140
141
  <div v-if="ann.text && ann.kind !== 'pronunciation'" class="ann-text">{{ ann.text }}</div>
141
142
  </div>
142
143
  </div>
@@ -149,6 +150,7 @@ onBeforeUnmount(() => {
149
150
  <div
150
151
  v-if="isMobile && stickyVisible && annotations.length"
151
152
  class="ann-sheet"
153
+ :class="{ vertical }"
152
154
  >
153
155
  <button class="ann-sheet-handle" @click="dismiss">
154
156
  <span class="ann-handle-bar" />
@@ -164,7 +166,7 @@ onBeforeUnmount(() => {
164
166
  <span v-if="layerLabel(ann)" class="ann-layer">{{ layerLabel(ann) }}</span>
165
167
  </div>
166
168
  <div class="ann-entry-body">
167
- <PronunciationGroup v-if="getSegment(ann)" :segment="getSegment(ann)!" />
169
+ <div v-if="getSegment(ann)" class="ann-pron-h"><PronunciationGroup :segment="getSegment(ann)!" /></div>
168
170
  <div v-if="ann.text && ann.kind !== 'pronunciation'" class="ann-text">{{ ann.text }}</div>
169
171
  </div>
170
172
  </div>
@@ -407,4 +409,80 @@ onBeforeUnmount(() => {
407
409
  @media (min-width: 768px) {
408
410
  .ann-sheet { display: none; }
409
411
  }
412
+
413
+ /* ─── Vertical mode ─── */
414
+ .ann-card.vertical {
415
+ writing-mode: vertical-rl;
416
+ text-orientation: mixed;
417
+ }
418
+
419
+ .ann-card.vertical .ann-card-scroll {
420
+ display: flex;
421
+ flex-direction: row;
422
+ padding: 10px 8px;
423
+ }
424
+
425
+ .ann-card.vertical .ann-entry {
426
+ border-bottom: none;
427
+ padding: 8px 4px;
428
+ }
429
+
430
+ .ann-card.vertical .ann-entry + .ann-entry {
431
+ border-top: 1px solid var(--border-light);
432
+ margin-top: 4px;
433
+ }
434
+
435
+ .ann-card.vertical .ann-card-close {
436
+ writing-mode: horizontal-tb;
437
+ }
438
+
439
+ .ann-card.vertical .ann-pron-h {
440
+ writing-mode: horizontal-tb;
441
+ }
442
+
443
+ .ann-card.vertical .ann-entry-body {
444
+ padding-left: 0;
445
+ padding-top: 4px;
446
+ }
447
+
448
+ .ann-card.vertical .ann-text {
449
+ white-space: pre-line;
450
+ line-height: 2;
451
+ }
452
+
453
+ .ann-sheet.vertical {
454
+ writing-mode: vertical-rl;
455
+ text-orientation: mixed;
456
+ }
457
+
458
+ .ann-sheet.vertical .ann-sheet-scroll {
459
+ display: flex;
460
+ flex-direction: column;
461
+ overflow-x: auto;
462
+ overflow-y: hidden;
463
+ padding: 4px 16px 24px;
464
+ }
465
+
466
+ .ann-sheet.vertical .ann-entry {
467
+ border-bottom: none;
468
+ border-left: 1px solid var(--border-light);
469
+ padding: 0 12px;
470
+ }
471
+
472
+ .ann-sheet.vertical .ann-entry:first-child {
473
+ border-left: none;
474
+ }
475
+
476
+ .ann-sheet.vertical .ann-pron-h {
477
+ writing-mode: horizontal-tb;
478
+ }
479
+
480
+ .ann-sheet.vertical .ann-text {
481
+ white-space: pre-line;
482
+ line-height: 2;
483
+ }
484
+
485
+ .ann-sheet.vertical .ann-sheet-handle {
486
+ writing-mode: horizontal-tb;
487
+ }
410
488
  </style>
@@ -160,11 +160,12 @@ export function useAnnotationTooltip() {
160
160
  bottom: '0',
161
161
  }
162
162
  } else if (layout.value === 'vertical') {
163
- // Vertical mode: card to the left of the annotation
164
- const cardW = 340
163
+ // Vertical mode: tall narrow card to the left of the annotation
164
+ const cardW = 180
165
+ const cardH = Math.min(vh - 16, 480)
165
166
  const gap = 12
166
167
  let left = Math.max(8, rect.left - cardW - gap)
167
- let top = Math.max(8, Math.min(rect.top, vh - 300))
168
+ let top = Math.max(8, Math.min(rect.top, vh - cardH))
168
169
 
169
170
  // If not enough room on left, go right
170
171
  if (rect.left - cardW - gap < 8) {
@@ -175,7 +176,7 @@ export function useAnnotationTooltip() {
175
176
  left: left + 'px',
176
177
  top: top + 'px',
177
178
  width: cardW + 'px',
178
- maxHeight: Math.min(vh - 16, 500) + 'px',
179
+ maxHeight: cardH + 'px',
179
180
  }
180
181
  } else {
181
182
  // Horizontal mode: card below/above the annotation
@@ -495,6 +495,7 @@ function tcy(n: number): string {
495
495
  :headwords="annotationHeadwords"
496
496
  :layer-labels="layerLabels"
497
497
  :active-id="paneActiveId"
498
+ :vertical="isVertical"
498
499
  @close="paneVisible = false"
499
500
  @select="onPaneSelect"
500
501
  />
@@ -711,6 +712,7 @@ function tcy(n: number): string {
711
712
  :headword="interaction.headword"
712
713
  :layer-labels="layerLabels"
713
714
  :style="interaction.style"
715
+ :vertical="isVertical"
714
716
  @close="interaction.dismiss"
715
717
  @tooltip-enter="interaction.onTooltipEnter"
716
718
  @tooltip-leave="interaction.onTooltipLeave"