@commonpub/layer 0.21.5 → 0.21.6

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.
@@ -34,7 +34,7 @@ const visible = computed(() => !hasConsented.value && hasNonEssentialCookies.val
34
34
  z-index: var(--z-toast);
35
35
  background: var(--surface);
36
36
  border-top: var(--border-width-default) solid var(--border);
37
- box-shadow: 0 -4px 12px rgba(0, 0, 0, 0.1);
37
+ box-shadow: 0 -2px 0 var(--border);
38
38
  }
39
39
 
40
40
  .cpub-consent-inner {
@@ -79,14 +79,14 @@ useFocusTrap(dialogRef, () => open.value, close);
79
79
  <style scoped>
80
80
  .cpub-rfd-overlay {
81
81
  position: fixed; inset: 0; z-index: 9999;
82
- background: rgba(0, 0, 0, 0.5); display: flex;
82
+ background: var(--color-surface-overlay, rgba(0, 0, 0, 0.5)); display: flex;
83
83
  align-items: center; justify-content: center;
84
84
  padding: 16px;
85
85
  }
86
86
  .cpub-rfd-dialog {
87
87
  background: var(--bg); border: var(--border-width-default) solid var(--border);
88
88
  width: 100%; max-width: 420px; padding: 24px;
89
- box-shadow: 4px 4px 0 var(--shadow);
89
+ box-shadow: var(--shadow-md);
90
90
  }
91
91
  .cpub-rfd-header {
92
92
  display: flex; align-items: center; justify-content: space-between;
@@ -10,6 +10,9 @@ const emit = defineEmits<{
10
10
  import: [md: string, mode: 'append' | 'replace'];
11
11
  }>();
12
12
 
13
+ const dialogRef = ref<HTMLElement | null>(null);
14
+ useFocusTrap(dialogRef, () => props.show, () => emit('close'));
15
+
13
16
  const activeTab = ref<'paste' | 'file'>('paste');
14
17
  const markdownText = ref('');
15
18
  const mode = ref<'append' | 'replace'>('append');
@@ -58,9 +61,9 @@ async function readFile(file: File): Promise<void> {
58
61
  <template>
59
62
  <Teleport to="body">
60
63
  <div v-if="show" class="md-import-overlay" @click.self="emit('close')">
61
- <div class="md-import-dialog">
64
+ <div ref="dialogRef" class="md-import-dialog" role="dialog" aria-modal="true" aria-labelledby="md-import-title">
62
65
  <div class="md-import-header">
63
- <h2><i class="fa-brands fa-markdown"></i> Import Markdown</h2>
66
+ <h2 id="md-import-title"><i class="fa-brands fa-markdown"></i> Import Markdown</h2>
64
67
  <button class="md-import-close" @click="emit('close')"><i class="fa-solid fa-xmark"></i></button>
65
68
  </div>
66
69
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@commonpub/layer",
3
- "version": "0.21.5",
3
+ "version": "0.21.6",
4
4
  "type": "module",
5
5
  "main": "./nuxt.config.ts",
6
6
  "files": [
@@ -50,16 +50,16 @@
50
50
  "vue": "^3.4.0",
51
51
  "vue-router": "^4.3.0",
52
52
  "zod": "^4.3.6",
53
- "@commonpub/auth": "0.6.0",
54
- "@commonpub/editor": "0.7.9",
55
53
  "@commonpub/docs": "0.6.3",
56
- "@commonpub/protocol": "0.9.10",
54
+ "@commonpub/config": "0.12.0",
57
55
  "@commonpub/learning": "0.5.2",
56
+ "@commonpub/auth": "0.6.0",
58
57
  "@commonpub/explainer": "0.7.12",
59
- "@commonpub/ui": "0.8.5",
60
- "@commonpub/server": "2.53.0",
61
58
  "@commonpub/schema": "0.16.0",
62
- "@commonpub/config": "0.12.0"
59
+ "@commonpub/editor": "0.7.9",
60
+ "@commonpub/protocol": "0.9.10",
61
+ "@commonpub/server": "2.53.1",
62
+ "@commonpub/ui": "0.8.5"
63
63
  },
64
64
  "devDependencies": {
65
65
  "@testing-library/jest-dom": "^6.9.1",
@@ -47,6 +47,23 @@ export default defineEventHandler(async (event) => {
47
47
  }
48
48
  userConnections.set(userId, current + 1);
49
49
 
50
+ // Decrement exactly once on disconnect. Registered at handler scope (not
51
+ // inside ReadableStream.start) because start() is invoked lazily when the
52
+ // runtime begins pulling the stream — if the client aborts before that,
53
+ // start() never runs and an in-start cleanup would never fire, leaking
54
+ // the slot permanently and eventually 429-locking the user for the
55
+ // process lifetime. cleanup() also calls release(); the guard makes it
56
+ // idempotent so there is no double-decrement.
57
+ let released = false;
58
+ const release = (): void => {
59
+ if (released) return;
60
+ released = true;
61
+ const next = (userConnections.get(userId) ?? 1) - 1;
62
+ if (next <= 0) userConnections.delete(userId);
63
+ else userConnections.set(userId, next);
64
+ };
65
+ event.node.req.on('close', release);
66
+
50
67
  const encoder = new TextEncoder();
51
68
  const stream = new ReadableStream({
52
69
  async start(controller) {
@@ -65,9 +82,7 @@ export default defineEventHandler(async (event) => {
65
82
  unsubscribe = null;
66
83
  }
67
84
  try { controller.close(); } catch { /* already closed */ }
68
- const next = (userConnections.get(userId) ?? 1) - 1;
69
- if (next <= 0) userConnections.delete(userId);
70
- else userConnections.set(userId, next);
85
+ release();
71
86
  }
72
87
 
73
88
  async function sendCounts(): Promise<void> {