experiments in a post-browser web
10
fork

Configure Feed

Select the types of activity you want to include in your feed.

fix(entities): align UI with groups/tags component and theme patterns

+793 -706
+226
extensions/entities/home.css
··· 1 + /* Import theme variables */ 2 + @import url('peek://theme/variables.css'); 3 + 4 + * { 5 + box-sizing: border-box; 6 + margin: 0; 7 + padding: 0; 8 + } 9 + 10 + html { 11 + font-family: var(--theme-font-sans); 12 + -webkit-font-smoothing: antialiased; 13 + font-size: 14px; 14 + line-height: 1.5; 15 + } 16 + 17 + body { 18 + background: var(--base00); 19 + color: var(--base05); 20 + min-height: 100vh; 21 + display: flex; 22 + flex-direction: column; 23 + } 24 + 25 + /* Header */ 26 + .header { 27 + display: flex; 28 + align-items: center; 29 + justify-content: space-between; 30 + padding: 16px 24px; 31 + border-bottom: 1px solid var(--base02); 32 + background: var(--base00); 33 + } 34 + 35 + .header-left { 36 + display: flex; 37 + align-items: center; 38 + gap: 12px; 39 + } 40 + 41 + .header-title { 42 + font-size: 18px; 43 + font-weight: 600; 44 + color: var(--base05); 45 + } 46 + 47 + .header-count { 48 + font-size: 12px; 49 + color: var(--base04); 50 + font-weight: normal; 51 + } 52 + 53 + /* Filter bar */ 54 + .filters { 55 + display: flex; 56 + gap: 4px; 57 + padding: 12px 24px; 58 + border-bottom: 1px solid var(--base02); 59 + flex-wrap: wrap; 60 + align-items: center; 61 + } 62 + 63 + .filter-btn { 64 + display: flex; 65 + align-items: center; 66 + gap: 4px; 67 + padding: 6px 10px; 68 + background: transparent; 69 + border: none; 70 + border-radius: 6px; 71 + cursor: pointer; 72 + color: var(--base04); 73 + font-size: 12px; 74 + transition: all 0.15s; 75 + } 76 + 77 + .filter-btn.active { 78 + color: var(--base0D); 79 + background: var(--base01); 80 + } 81 + 82 + .filter-btn:not(.active):hover { 83 + color: var(--base05); 84 + background: var(--base01); 85 + } 86 + 87 + /* Search */ 88 + .search-container { 89 + padding: 16px 24px; 90 + } 91 + 92 + peek-input.search-input { 93 + width: 100%; 94 + --peek-input-bg: var(--base01); 95 + --peek-input-border: var(--base02); 96 + --peek-input-height: 40px; 97 + } 98 + 99 + /* Content */ 100 + .content { 101 + flex: 1; 102 + overflow-y: auto; 103 + padding: 0 24px 24px 24px; 104 + } 105 + 106 + /* Cards grid - peek-grid handles layout */ 107 + peek-grid { 108 + --peek-grid-min-item-width: 280px; 109 + --peek-grid-gap: 12px; 110 + } 111 + 112 + /* Card customization - peek-card custom properties */ 113 + peek-card { 114 + --peek-card-bg: var(--base01); 115 + --peek-card-border: transparent; 116 + --peek-card-radius: 8px; 117 + --peek-card-padding: 14px; 118 + --peek-card-gap: 10px; 119 + cursor: pointer; 120 + } 121 + 122 + peek-card[selected] { 123 + --peek-card-bg: var(--base02); 124 + outline: 2px solid var(--base0D); 125 + outline-offset: -2px; 126 + } 127 + 128 + /* Entity type icon */ 129 + .entity-type-icon { 130 + display: inline-flex; 131 + align-items: center; 132 + justify-content: center; 133 + width: 24px; 134 + height: 24px; 135 + border-radius: 50%; 136 + font-size: 13px; 137 + flex-shrink: 0; 138 + } 139 + 140 + .type-person { background: var(--base0D); color: var(--base00); } 141 + .type-organization { background: var(--base0B); color: var(--base00); } 142 + .type-place { background: var(--base0A); color: var(--base00); } 143 + .type-event { background: var(--base0E); color: var(--base00); } 144 + .type-email { background: var(--base0C); color: var(--base00); } 145 + .type-phone { background: var(--base09); color: var(--base00); } 146 + .type-date { background: var(--base0E); color: var(--base00); } 147 + .type-product { background: var(--base08); color: var(--base00); } 148 + .type-creative_work { background: var(--base04); color: var(--base00); } 149 + .type-price { background: var(--base0B); color: var(--base00); } 150 + .type-tracking_number { background: var(--base09); color: var(--base00); } 151 + 152 + /* Card slotted content */ 153 + .card-header { 154 + display: flex; 155 + align-items: center; 156 + gap: 8px; 157 + } 158 + 159 + .entity-name { 160 + font-size: 14px; 161 + font-weight: 500; 162 + color: var(--base05); 163 + white-space: nowrap; 164 + overflow: hidden; 165 + text-overflow: ellipsis; 166 + } 167 + 168 + .entity-type { 169 + font-size: 11px; 170 + color: var(--base04); 171 + text-transform: capitalize; 172 + } 173 + 174 + .entity-confidence { 175 + font-size: 11px; 176 + color: var(--base04); 177 + } 178 + 179 + .entity-meta { 180 + font-size: 12px; 181 + color: var(--base04); 182 + margin-top: 4px; 183 + } 184 + 185 + .entity-attrs { 186 + font-size: 12px; 187 + color: var(--base04); 188 + margin-top: 4px; 189 + } 190 + 191 + .entity-attrs span { 192 + display: inline-block; 193 + margin-right: 8px; 194 + } 195 + 196 + .card-body { 197 + padding: 4px 0; 198 + } 199 + 200 + .card-footer { 201 + display: flex; 202 + justify-content: space-between; 203 + align-items: center; 204 + font-size: 11px; 205 + color: var(--base03); 206 + } 207 + 208 + /* Empty state */ 209 + .empty-state { 210 + grid-column: 1 / -1; 211 + text-align: center; 212 + padding: 48px 24px; 213 + color: var(--base03); 214 + font-size: 14px; 215 + } 216 + 217 + .empty-state h2 { 218 + font-size: 18px; 219 + font-weight: 500; 220 + margin-bottom: 8px; 221 + } 222 + 223 + .empty-state p { 224 + font-size: 14px; 225 + margin-bottom: 16px; 226 + }
+60 -231
extensions/entities/home.html
··· 1 1 <!DOCTYPE html> 2 2 <html> 3 - <head> 4 - <meta charset="utf-8"> 5 - <meta http-equiv="Content-Security-Policy" content="script-src 'self' 'unsafe-inline';"> 6 - <meta name="viewport" content="width=device-width,user-scalable=no,initial-scale=1"> 7 - <title>Entities</title> 3 + <head> 4 + <meta charset="utf-8"> 5 + <meta http-equiv="Content-Security-Policy" content="script-src 'self' 'unsafe-inline';"> 6 + <meta name="viewport" content="width=device-width,user-scalable=no,initial-scale=1"> 7 + <title>Entities</title> 8 + <link rel="stylesheet" type="text/css" href="home.css"> 8 9 9 - <!-- Import map for resolving bare module specifiers --> 10 - <script type="importmap"> 11 - { 12 - "imports": { 13 - "lit": "peek://node_modules/lit/index.js", 14 - "lit/": "peek://node_modules/lit/", 15 - "lit-html": "peek://node_modules/lit-html/lit-html.js", 16 - "lit-html/": "peek://node_modules/lit-html/", 17 - "lit-element": "peek://node_modules/lit-element/lit-element.js", 18 - "lit-element/": "peek://node_modules/lit-element/", 19 - "@lit/reactive-element": "peek://node_modules/@lit/reactive-element/reactive-element.js", 20 - "@lit/reactive-element/": "peek://node_modules/@lit/reactive-element/" 21 - } 22 - } 23 - </script> 24 - 25 - <!-- Import peek-components --> 26 - <script type="module"> 27 - import 'peek://app/components/peek-card.js'; 28 - import 'peek://app/components/peek-grid.js'; 29 - import 'peek://app/components/peek-input.js'; 30 - import 'peek://app/components/peek-button.js'; 31 - import 'peek://app/components/peek-button-group.js'; 32 - </script> 33 - 34 - <style> 35 - * { 36 - box-sizing: border-box; 37 - margin: 0; 38 - padding: 0; 39 - } 40 - 41 - body { 42 - font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif; 43 - background: var(--base00, #1a1a1a); 44 - color: var(--base05, #e0e0e0); 45 - height: 100vh; 46 - display: flex; 47 - flex-direction: column; 48 - } 49 - 50 - header { 51 - display: flex; 52 - align-items: center; 53 - gap: 12px; 54 - padding: 12px 16px; 55 - background: var(--base01, #252525); 56 - border-bottom: 1px solid var(--base02, #333); 57 - } 58 - 59 - header h1 { 60 - font-size: 16px; 61 - font-weight: 500; 62 - flex: 1; 10 + <!-- Import map for resolving bare module specifiers --> 11 + <script type="importmap"> 12 + { 13 + "imports": { 14 + "lit": "peek://node_modules/lit/index.js", 15 + "lit/": "peek://node_modules/lit/", 16 + "lit-html": "peek://node_modules/lit-html/lit-html.js", 17 + "lit-html/": "peek://node_modules/lit-html/", 18 + "lit-element": "peek://node_modules/lit-element/lit-element.js", 19 + "lit-element/": "peek://node_modules/lit-element/", 20 + "@lit/reactive-element": "peek://node_modules/@lit/reactive-element/reactive-element.js", 21 + "@lit/reactive-element/": "peek://node_modules/@lit/reactive-element/" 22 + } 63 23 } 24 + </script> 64 25 65 - .header-count { 66 - font-size: 12px; 67 - color: var(--base04, #888); 68 - font-weight: normal; 69 - } 26 + <!-- Import peek-components --> 27 + <script type="module"> 28 + import 'peek://app/components/peek-card.js'; 29 + import 'peek://app/components/peek-grid.js'; 30 + import 'peek://app/components/peek-input.js'; 31 + import 'peek://app/components/peek-button.js'; 32 + import 'peek://app/components/peek-button-group.js'; 33 + </script> 34 + </head> 35 + <body> 36 + <header class="header"> 37 + <div class="header-left"> 38 + <h1 class="header-title">Entities <span class="header-count" id="entityCount"></span></h1> 39 + </div> 40 + <peek-button id="extractBtn" variant="ghost" size="sm">Extract Current Page</peek-button> 41 + </header> 70 42 71 - .filters { 72 - display: flex; 73 - gap: 8px; 74 - padding: 12px 16px; 75 - background: var(--base01, #252525); 76 - border-bottom: 1px solid var(--base02, #333); 77 - flex-wrap: wrap; 78 - align-items: center; 79 - } 43 + <div class="filters" id="filters"> 44 + <button class="filter-btn active" data-type="">All</button> 45 + <button class="filter-btn" data-type="person">People</button> 46 + <button class="filter-btn" data-type="organization">Orgs</button> 47 + <button class="filter-btn" data-type="place">Places</button> 48 + <button class="filter-btn" data-type="event">Events</button> 49 + <button class="filter-btn" data-type="email">Emails</button> 50 + <button class="filter-btn" data-type="phone">Phones</button> 51 + <button class="filter-btn" data-type="date">Dates</button> 52 + <button class="filter-btn" data-type="product">Products</button> 53 + </div> 80 54 81 - .filter-btn { 82 - background: var(--base02, #333); 83 - border: 1px solid var(--base03, #444); 84 - color: var(--base05, #e0e0e0); 85 - padding: 4px 10px; 86 - border-radius: 12px; 87 - cursor: pointer; 88 - font-size: 12px; 89 - transition: all 0.15s; 90 - } 55 + <div class="search-container"> 56 + <peek-input 57 + class="search-input" 58 + id="searchInput" 59 + placeholder="Search entities..." 60 + type="search" 61 + ></peek-input> 62 + </div> 91 63 92 - .filter-btn:hover { 93 - background: var(--base03, #444); 94 - } 64 + <div class="content"> 65 + <peek-grid id="entityGrid" min-item-width="280" gap="12"></peek-grid> 66 + </div> 95 67 96 - .filter-btn.active { 97 - background: var(--blue, #4a9eff); 98 - border-color: var(--blue, #4a9eff); 99 - color: white; 100 - } 101 - 102 - .search-container { 103 - padding: 8px 16px; 104 - } 105 - 106 - .content { 107 - flex: 1; 108 - overflow-y: auto; 109 - padding: 16px; 110 - } 111 - 112 - .entity-type-icon { 113 - display: inline-block; 114 - width: 24px; 115 - height: 24px; 116 - border-radius: 50%; 117 - text-align: center; 118 - line-height: 24px; 119 - font-size: 13px; 120 - margin-right: 6px; 121 - flex-shrink: 0; 122 - } 123 - 124 - .type-person { background: var(--blue, #4a9eff); color: white; } 125 - .type-organization { background: var(--green, #4aff9e); color: #1a1a1a; } 126 - .type-place { background: var(--yellow, #ffcc4a); color: #1a1a1a; } 127 - .type-event { background: var(--magenta, #ff4adb); color: white; } 128 - .type-email { background: var(--cyan, #4affee); color: #1a1a1a; } 129 - .type-phone { background: var(--orange, #ff8c4a); color: white; } 130 - .type-date { background: var(--violet, #9b4aff); color: white; } 131 - .type-product { background: var(--red, #ff4a4a); color: white; } 132 - .type-creative_work { background: var(--base04, #888); color: white; } 133 - .type-price { background: var(--green, #4aff9e); color: #1a1a1a; } 134 - .type-tracking_number { background: var(--orange, #ff8c4a); color: white; } 135 - 136 - .entity-name { 137 - font-weight: 500; 138 - font-size: 14px; 139 - } 140 - 141 - .entity-type { 142 - font-size: 11px; 143 - color: var(--base04, #888); 144 - text-transform: capitalize; 145 - } 146 - 147 - .entity-confidence { 148 - font-size: 11px; 149 - color: var(--base04, #888); 150 - } 151 - 152 - .entity-meta { 153 - font-size: 12px; 154 - color: var(--base04, #888); 155 - margin-top: 4px; 156 - } 157 - 158 - .entity-attrs { 159 - font-size: 12px; 160 - color: var(--base04, #aaa); 161 - margin-top: 4px; 162 - } 163 - 164 - .entity-attrs span { 165 - display: inline-block; 166 - margin-right: 8px; 167 - } 168 - 169 - .empty-state { 170 - text-align: center; 171 - padding: 60px 20px; 172 - color: var(--base04, #888); 173 - } 174 - 175 - .empty-state h2 { 176 - font-size: 18px; 177 - font-weight: 500; 178 - margin-bottom: 8px; 179 - } 180 - 181 - .empty-state p { 182 - font-size: 14px; 183 - margin-bottom: 16px; 184 - } 185 - 186 - peek-card { 187 - cursor: pointer; 188 - } 189 - 190 - .card-header { 191 - display: flex; 192 - align-items: center; 193 - gap: 6px; 194 - } 195 - 196 - .card-body { 197 - padding: 4px 0; 198 - } 199 - 200 - .card-footer { 201 - display: flex; 202 - justify-content: space-between; 203 - align-items: center; 204 - font-size: 11px; 205 - color: var(--base04, #888); 206 - } 207 - </style> 208 - </head> 209 - <body> 210 - <header> 211 - <h1>Entities <span class="header-count" id="entityCount"></span></h1> 212 - <peek-button id="extractBtn" variant="ghost" size="sm">Extract Current Page</peek-button> 213 - </header> 214 - 215 - <div class="filters" id="filters"> 216 - <button class="filter-btn active" data-type="">All</button> 217 - <button class="filter-btn" data-type="person">People</button> 218 - <button class="filter-btn" data-type="organization">Orgs</button> 219 - <button class="filter-btn" data-type="place">Places</button> 220 - <button class="filter-btn" data-type="event">Events</button> 221 - <button class="filter-btn" data-type="email">Emails</button> 222 - <button class="filter-btn" data-type="phone">Phones</button> 223 - <button class="filter-btn" data-type="date">Dates</button> 224 - <button class="filter-btn" data-type="product">Products</button> 225 - </div> 226 - 227 - <div class="search-container"> 228 - <peek-input 229 - id="searchInput" 230 - placeholder="Search entities..." 231 - type="search" 232 - ></peek-input> 233 - </div> 234 - 235 - <div class="content"> 236 - <peek-grid id="entityGrid" min-item-width="280" gap="12"></peek-grid> 237 - </div> 238 - 239 - <script type="module" src="home.js"></script> 240 - </body> 68 + <script type="module" src="home.js"></script> 69 + </body> 241 70 </html>
+27 -26
extensions/hud/hud.html
··· 1 1 <!DOCTYPE html> 2 2 <html> 3 - <head> 4 - <meta charset="UTF-8"> 5 - <meta name="viewport" content="width=device-width, initial-scale=1.0"> 6 - <title>HUD</title> 7 - <link rel="stylesheet" href="./styles.css"> 8 - </head> 9 - <body> 10 - <div id="hud-container"> 11 - <div class="hud-section"> 12 - <div class="hud-label">Mode</div> 13 - <div id="mode-value" class="hud-value">-</div> 14 - </div> 3 + <head> 4 + <meta charset="utf-8"> 5 + <meta http-equiv="Content-Security-Policy" content="script-src 'self' 'unsafe-inline';"> 6 + <meta name="viewport" content="width=device-width,user-scalable=no,initial-scale=1"> 7 + <title>HUD</title> 8 + <link rel="stylesheet" type="text/css" href="styles.css"> 9 + </head> 10 + <body> 11 + <div id="hud-container"> 12 + <div class="hud-section"> 13 + <div class="hud-label">Mode</div> 14 + <div id="mode-value" class="hud-value">-</div> 15 + </div> 15 16 16 - <div class="hud-section"> 17 - <div class="hud-label">IZUI State</div> 18 - <div id="izui-value" class="hud-value">-</div> 19 - </div> 17 + <div class="hud-section"> 18 + <div class="hud-label">IZUI State</div> 19 + <div id="izui-value" class="hud-value">-</div> 20 + </div> 20 21 21 - <div class="hud-section"> 22 - <div class="hud-label">Active Window</div> 23 - <div id="window-title" class="hud-value hud-truncate">-</div> 24 - </div> 22 + <div class="hud-section"> 23 + <div class="hud-label">Active Window</div> 24 + <div id="window-title" class="hud-value hud-truncate">-</div> 25 + </div> 25 26 26 - <div class="hud-section"> 27 - <div class="hud-label">Stats</div> 28 - <div id="stats-value" class="hud-value hud-small">-</div> 27 + <div class="hud-section"> 28 + <div class="hud-label">Stats</div> 29 + <div id="stats-value" class="hud-value hud-small">-</div> 30 + </div> 29 31 </div> 30 - </div> 31 32 32 - <script type="module" src="./hud.js"></script> 33 - </body> 33 + <script type="module" src="hud.js"></script> 34 + </body> 34 35 </html>
+27 -18
extensions/hud/styles.css
··· 1 + /* Import theme variables */ 2 + @import url('peek://theme/variables.css'); 3 + 1 4 * { 2 5 margin: 0; 3 6 padding: 0; 4 7 box-sizing: border-box; 5 8 } 6 9 10 + html { 11 + font-family: var(--theme-font-sans); 12 + -webkit-font-smoothing: antialiased; 13 + font-size: 12px; 14 + line-height: 1.5; 15 + } 16 + 7 17 html, body { 8 18 width: 100%; 9 19 height: 100%; ··· 16 26 width: 100%; 17 27 height: 100%; 18 28 padding: 12px; 19 - background: rgba(0, 0, 0, 0.85); 29 + background: var(--base00); 20 30 backdrop-filter: blur(10px); 21 31 -webkit-backdrop-filter: blur(10px); 22 32 border-radius: 8px; 23 - border: 1px solid rgba(255, 255, 255, 0.1); 24 - color: #fff; 25 - font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif; 33 + border: 1px solid var(--base02); 34 + color: var(--base05); 26 35 font-size: 12px; 27 - box-shadow: 0 4px 12px rgba(0, 0, 0, 0.5); 36 + box-shadow: 0 4px 12px rgba(0, 0, 0, 0.3); 28 37 -webkit-app-region: no-drag; 29 38 } 30 39 31 40 .hud-section { 32 41 margin-bottom: 10px; 33 42 padding-bottom: 8px; 34 - border-bottom: 1px solid rgba(255, 255, 255, 0.1); 43 + border-bottom: 1px solid var(--base02); 35 44 } 36 45 37 46 .hud-section:last-child { ··· 45 54 font-weight: 600; 46 55 text-transform: uppercase; 47 56 letter-spacing: 0.5px; 48 - color: rgba(255, 255, 255, 0.6); 57 + color: var(--base04); 49 58 margin-bottom: 4px; 50 59 } 51 60 52 61 .hud-value { 53 62 font-size: 13px; 54 63 font-weight: 500; 55 - color: #fff; 64 + color: var(--base05); 56 65 line-height: 1.4; 57 66 } 58 67 ··· 68 77 line-height: 1.5; 69 78 } 70 79 71 - /* Mode-specific colors */ 80 + /* Mode-specific colors using theme accent variables */ 72 81 .mode-default { 73 - color: #60a5fa; 82 + color: var(--base0D); 74 83 } 75 84 76 85 .mode-page { 77 - color: #34d399; 86 + color: var(--base0B); 78 87 } 79 88 80 89 .mode-group { 81 - color: #f472b6; 90 + color: var(--base0E); 82 91 } 83 92 84 93 .mode-settings { 85 - color: #fbbf24; 94 + color: var(--base0A); 86 95 } 87 96 88 - /* IZUI state colors */ 97 + /* IZUI state colors using theme accent variables */ 89 98 .izui-idle { 90 - color: #9ca3af; 99 + color: var(--base04); 91 100 } 92 101 93 102 .izui-transient { 94 - color: #60a5fa; 103 + color: var(--base0D); 95 104 } 96 105 97 106 .izui-active { 98 - color: #34d399; 107 + color: var(--base0B); 99 108 } 100 109 101 110 .izui-overlay { 102 - color: #f472b6; 111 + color: var(--base0E); 103 112 }
+360
extensions/scripts/manager.css
··· 1 + /* Import theme variables */ 2 + @import url('peek://theme/variables.css'); 3 + 4 + * { 5 + box-sizing: border-box; 6 + margin: 0; 7 + padding: 0; 8 + } 9 + 10 + html { 11 + font-family: var(--theme-font-sans); 12 + -webkit-font-smoothing: antialiased; 13 + font-size: 14px; 14 + line-height: 1.5; 15 + } 16 + 17 + body { 18 + background: var(--base00); 19 + color: var(--base05); 20 + height: 100vh; 21 + overflow: hidden; 22 + } 23 + 24 + .container { 25 + display: flex; 26 + height: 100vh; 27 + } 28 + 29 + /* Left Panel - Scripts List */ 30 + .scripts-list { 31 + width: 300px; 32 + background: var(--base01); 33 + border-right: 1px solid var(--base02); 34 + display: flex; 35 + flex-direction: column; 36 + } 37 + 38 + .scripts-header { 39 + padding: 16px; 40 + border-bottom: 1px solid var(--base02); 41 + } 42 + 43 + .scripts-header h1 { 44 + font-size: 18px; 45 + font-weight: 600; 46 + margin-bottom: 12px; 47 + color: var(--base05); 48 + } 49 + 50 + .scripts-items { 51 + flex: 1; 52 + overflow-y: auto; 53 + padding: 8px; 54 + } 55 + 56 + .script-item { 57 + padding: 12px; 58 + margin-bottom: 4px; 59 + background: var(--base02); 60 + border-radius: 6px; 61 + cursor: pointer; 62 + border: 2px solid transparent; 63 + transition: all 0.15s; 64 + } 65 + 66 + .script-item:hover { 67 + background: var(--base03); 68 + } 69 + 70 + .script-item.active { 71 + border-color: var(--base0D); 72 + background: var(--base03); 73 + } 74 + 75 + .script-item-header { 76 + display: flex; 77 + align-items: center; 78 + gap: 8px; 79 + margin-bottom: 4px; 80 + } 81 + 82 + .script-checkbox { 83 + margin: 0; 84 + accent-color: var(--base0D); 85 + } 86 + 87 + .script-name { 88 + flex: 1; 89 + font-weight: 500; 90 + font-size: 14px; 91 + color: var(--base05); 92 + } 93 + 94 + .script-status { 95 + width: 8px; 96 + height: 8px; 97 + border-radius: 50%; 98 + background: var(--base04); 99 + } 100 + 101 + .script-status.success { 102 + background: var(--base0B); 103 + } 104 + 105 + .script-status.error { 106 + background: var(--base08); 107 + } 108 + 109 + .script-meta { 110 + font-size: 11px; 111 + color: var(--base04); 112 + margin-left: 28px; 113 + } 114 + 115 + /* Center Panel - Editor */ 116 + .editor-panel { 117 + flex: 1; 118 + display: flex; 119 + flex-direction: column; 120 + background: var(--base00); 121 + } 122 + 123 + .editor-header { 124 + padding: 16px; 125 + border-bottom: 1px solid var(--base02); 126 + } 127 + 128 + .editor-form { 129 + display: flex; 130 + flex-direction: column; 131 + gap: 12px; 132 + } 133 + 134 + .form-row { 135 + display: flex; 136 + gap: 12px; 137 + } 138 + 139 + .form-group { 140 + display: flex; 141 + flex-direction: column; 142 + gap: 4px; 143 + } 144 + 145 + .form-group.flex-1 { 146 + flex: 1; 147 + } 148 + 149 + .form-group.w-150 { 150 + width: 150px; 151 + } 152 + 153 + .form-group label { 154 + font-size: 12px; 155 + color: var(--base04); 156 + font-weight: 500; 157 + } 158 + 159 + /* peek-input customization in form context */ 160 + .form-group peek-input { 161 + --peek-input-bg: var(--base01); 162 + --peek-input-border: var(--base02); 163 + --peek-input-height: 34px; 164 + } 165 + 166 + .form-group select { 167 + padding: 6px 8px; 168 + background: var(--base01); 169 + border: 1px solid var(--base02); 170 + color: var(--base05); 171 + border-radius: 6px; 172 + font-size: 13px; 173 + font-family: var(--theme-font-sans); 174 + height: 34px; 175 + } 176 + 177 + .form-group select:focus { 178 + outline: none; 179 + border-color: var(--base0D); 180 + } 181 + 182 + .editor-content { 183 + flex: 1; 184 + display: flex; 185 + flex-direction: column; 186 + padding: 16px; 187 + } 188 + 189 + .code-editor { 190 + flex: 1; 191 + background: var(--base01); 192 + color: var(--base05); 193 + border: 1px solid var(--base02); 194 + border-radius: 6px; 195 + padding: 12px; 196 + font-family: var(--theme-font-mono, 'Monaco', 'Menlo', 'Consolas', monospace); 197 + font-size: 13px; 198 + resize: none; 199 + outline: none; 200 + line-height: 1.5; 201 + } 202 + 203 + .code-editor:focus { 204 + border-color: var(--base0D); 205 + } 206 + 207 + .code-editor::placeholder { 208 + color: var(--base04); 209 + } 210 + 211 + .editor-actions { 212 + padding: 16px; 213 + border-top: 1px solid var(--base02); 214 + display: flex; 215 + gap: 8px; 216 + } 217 + 218 + /* Right Panel - Preview */ 219 + .preview-panel { 220 + width: 350px; 221 + background: var(--base01); 222 + border-left: 1px solid var(--base02); 223 + display: flex; 224 + flex-direction: column; 225 + } 226 + 227 + .preview-header { 228 + padding: 16px; 229 + border-bottom: 1px solid var(--base02); 230 + } 231 + 232 + .preview-header h2 { 233 + font-size: 14px; 234 + font-weight: 600; 235 + margin-bottom: 12px; 236 + color: var(--base05); 237 + } 238 + 239 + .test-url-group { 240 + display: flex; 241 + flex-direction: column; 242 + gap: 8px; 243 + } 244 + 245 + /* peek-input customization for test URL */ 246 + .test-url-group peek-input { 247 + --peek-input-bg: var(--base02); 248 + --peek-input-border: var(--base03); 249 + --peek-input-height: 36px; 250 + } 251 + 252 + .preview-content { 253 + flex: 1; 254 + padding: 16px; 255 + overflow-y: auto; 256 + } 257 + 258 + .result-box { 259 + background: var(--base02); 260 + border: 1px solid var(--base03); 261 + border-radius: 6px; 262 + padding: 12px; 263 + margin-bottom: 12px; 264 + } 265 + 266 + .result-status { 267 + display: flex; 268 + align-items: center; 269 + gap: 8px; 270 + margin-bottom: 8px; 271 + font-size: 13px; 272 + } 273 + 274 + .result-status.success { 275 + color: var(--base0B); 276 + } 277 + 278 + .result-status.error { 279 + color: var(--base08); 280 + } 281 + 282 + .result-status.skipped { 283 + color: var(--base0A); 284 + } 285 + 286 + .result-time { 287 + color: var(--base04); 288 + font-size: 12px; 289 + } 290 + 291 + .result-label { 292 + font-size: 12px; 293 + color: var(--base04); 294 + font-weight: 500; 295 + margin-top: 12px; 296 + } 297 + 298 + .result-data { 299 + background: var(--base00); 300 + padding: 8px; 301 + border-radius: 4px; 302 + font-family: var(--theme-font-mono, 'Monaco', 'Menlo', 'Consolas', monospace); 303 + font-size: 12px; 304 + overflow-x: auto; 305 + white-space: pre-wrap; 306 + color: var(--base05); 307 + margin-top: 4px; 308 + } 309 + 310 + .result-reason { 311 + font-size: 12px; 312 + color: var(--base04); 313 + } 314 + 315 + .result-stack { 316 + margin-top: 8px; 317 + font-size: 11px; 318 + color: var(--base04); 319 + } 320 + 321 + .result-stack pre { 322 + margin-top: 4px; 323 + font-family: var(--theme-font-mono, 'Monaco', 'Menlo', 'Consolas', monospace); 324 + white-space: pre-wrap; 325 + } 326 + 327 + .empty-state { 328 + color: var(--base04); 329 + text-align: center; 330 + padding: 40px 20px; 331 + font-size: 13px; 332 + } 333 + 334 + .console-output { 335 + margin-top: 12px; 336 + } 337 + 338 + .console-output h3 { 339 + font-size: 12px; 340 + color: var(--base04); 341 + margin-bottom: 8px; 342 + } 343 + 344 + .console-line { 345 + font-family: var(--theme-font-mono, 'Monaco', 'Menlo', 'Consolas', monospace); 346 + font-size: 11px; 347 + padding: 2px 0; 348 + } 349 + 350 + .console-line.log { 351 + color: var(--base05); 352 + } 353 + 354 + .console-line.error { 355 + color: var(--base08); 356 + } 357 + 358 + .console-line.warn { 359 + color: var(--base0A); 360 + }
+83 -421
extensions/scripts/manager.html
··· 1 1 <!DOCTYPE html> 2 2 <html> 3 - <head> 4 - <meta charset="utf-8"> 5 - <title>Scripts Manager</title> 6 - <style> 7 - * { 8 - box-sizing: border-box; 9 - margin: 0; 10 - padding: 0; 11 - } 12 - 13 - body { 14 - font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif; 15 - background: #1e1e1e; 16 - color: #d4d4d4; 17 - height: 100vh; 18 - overflow: hidden; 19 - } 20 - 21 - .container { 22 - display: flex; 23 - height: 100vh; 24 - } 25 - 26 - /* Left Panel - Scripts List */ 27 - .scripts-list { 28 - width: 300px; 29 - background: #252526; 30 - border-right: 1px solid #3e3e42; 31 - display: flex; 32 - flex-direction: column; 33 - } 34 - 35 - .scripts-header { 36 - padding: 16px; 37 - border-bottom: 1px solid #3e3e42; 38 - } 39 - 40 - .scripts-header h1 { 41 - font-size: 18px; 42 - font-weight: 600; 43 - margin-bottom: 12px; 44 - } 45 - 46 - .new-script-btn { 47 - width: 100%; 48 - padding: 8px; 49 - background: #0e639c; 50 - color: white; 51 - border: none; 52 - border-radius: 4px; 53 - cursor: pointer; 54 - font-size: 14px; 55 - } 56 - 57 - .new-script-btn:hover { 58 - background: #1177bb; 59 - } 60 - 61 - .scripts-items { 62 - flex: 1; 63 - overflow-y: auto; 64 - padding: 8px; 65 - } 66 - 67 - .script-item { 68 - padding: 12px; 69 - margin-bottom: 4px; 70 - background: #2d2d30; 71 - border-radius: 4px; 72 - cursor: pointer; 73 - border: 2px solid transparent; 74 - } 75 - 76 - .script-item:hover { 77 - background: #37373d; 78 - } 79 - 80 - .script-item.active { 81 - border-color: #0e639c; 82 - background: #37373d; 83 - } 84 - 85 - .script-item-header { 86 - display: flex; 87 - align-items: center; 88 - gap: 8px; 89 - margin-bottom: 4px; 90 - } 91 - 92 - .script-checkbox { 93 - margin: 0; 94 - } 95 - 96 - .script-name { 97 - flex: 1; 98 - font-weight: 500; 99 - font-size: 14px; 100 - } 101 - 102 - .script-status { 103 - width: 8px; 104 - height: 8px; 105 - border-radius: 50%; 106 - background: #808080; 107 - } 108 - 109 - .script-status.success { 110 - background: #4ec9b0; 111 - } 112 - 113 - .script-status.error { 114 - background: #f48771; 115 - } 116 - 117 - .script-meta { 118 - font-size: 11px; 119 - color: #858585; 120 - margin-left: 28px; 121 - } 122 - 123 - /* Center Panel - Editor */ 124 - .editor-panel { 125 - flex: 1; 126 - display: flex; 127 - flex-direction: column; 128 - background: #1e1e1e; 129 - } 130 - 131 - .editor-header { 132 - padding: 16px; 133 - border-bottom: 1px solid #3e3e42; 134 - } 135 - 136 - .editor-form { 137 - display: flex; 138 - flex-direction: column; 139 - gap: 12px; 140 - } 141 - 142 - .form-group { 143 - display: flex; 144 - flex-direction: column; 145 - gap: 4px; 146 - } 147 - 148 - .form-group label { 149 - font-size: 12px; 150 - color: #858585; 151 - } 152 - 153 - .form-group input, 154 - .form-group select { 155 - padding: 6px 8px; 156 - background: #3c3c3c; 157 - border: 1px solid #3e3e42; 158 - color: #d4d4d4; 159 - border-radius: 3px; 160 - font-size: 13px; 161 - } 162 - 163 - .form-group input:focus, 164 - .form-group select:focus { 165 - outline: none; 166 - border-color: #0e639c; 167 - } 168 - 169 - .editor-content { 170 - flex: 1; 171 - display: flex; 172 - flex-direction: column; 173 - padding: 16px; 174 - } 175 - 176 - .code-editor { 177 - flex: 1; 178 - background: #1e1e1e; 179 - color: #d4d4d4; 180 - border: 1px solid #3e3e42; 181 - border-radius: 4px; 182 - padding: 12px; 183 - font-family: 'Monaco', 'Menlo', 'Consolas', monospace; 184 - font-size: 13px; 185 - resize: none; 186 - outline: none; 187 - } 188 - 189 - .code-editor:focus { 190 - border-color: #0e639c; 191 - } 192 - 193 - .editor-actions { 194 - padding: 16px; 195 - border-top: 1px solid #3e3e42; 196 - display: flex; 197 - gap: 8px; 198 - } 199 - 200 - .btn { 201 - padding: 8px 16px; 202 - border: none; 203 - border-radius: 4px; 204 - cursor: pointer; 205 - font-size: 13px; 206 - } 207 - 208 - .btn-primary { 209 - background: #0e639c; 210 - color: white; 211 - } 212 - 213 - .btn-primary:hover { 214 - background: #1177bb; 215 - } 216 - 217 - .btn-danger { 218 - background: #a1260d; 219 - color: white; 220 - } 221 - 222 - .btn-danger:hover { 223 - background: #c72e0d; 224 - } 225 - 226 - .btn-secondary { 227 - background: #3c3c3c; 228 - color: #d4d4d4; 229 - } 230 - 231 - .btn-secondary:hover { 232 - background: #505050; 233 - } 234 - 235 - /* Right Panel - Preview */ 236 - .preview-panel { 237 - width: 350px; 238 - background: #252526; 239 - border-left: 1px solid #3e3e42; 240 - display: flex; 241 - flex-direction: column; 242 - } 243 - 244 - .preview-header { 245 - padding: 16px; 246 - border-bottom: 1px solid #3e3e42; 247 - } 248 - 249 - .preview-header h2 { 250 - font-size: 14px; 251 - font-weight: 600; 252 - margin-bottom: 12px; 253 - } 254 - 255 - .test-url-group { 256 - display: flex; 257 - flex-direction: column; 258 - gap: 8px; 259 - } 260 - 261 - .test-url-input { 262 - padding: 8px; 263 - background: #3c3c3c; 264 - border: 1px solid #3e3e42; 265 - color: #d4d4d4; 266 - border-radius: 3px; 267 - font-size: 13px; 268 - } 269 - 270 - .test-btn { 271 - padding: 8px; 272 - background: #0e639c; 273 - color: white; 274 - border: none; 275 - border-radius: 4px; 276 - cursor: pointer; 277 - font-size: 13px; 278 - } 279 - 280 - .test-btn:hover { 281 - background: #1177bb; 282 - } 283 - 284 - .test-btn:disabled { 285 - background: #505050; 286 - cursor: not-allowed; 287 - } 288 - 289 - .preview-content { 290 - flex: 1; 291 - padding: 16px; 292 - overflow-y: auto; 293 - } 294 - 295 - .result-box { 296 - background: #2d2d30; 297 - border: 1px solid #3e3e42; 298 - border-radius: 4px; 299 - padding: 12px; 300 - margin-bottom: 12px; 301 - } 302 - 303 - .result-status { 304 - display: flex; 305 - align-items: center; 306 - gap: 8px; 307 - margin-bottom: 8px; 308 - font-size: 13px; 309 - } 310 - 311 - .result-status.success { 312 - color: #4ec9b0; 313 - } 314 - 315 - .result-status.error { 316 - color: #f48771; 317 - } 318 - 319 - .result-time { 320 - color: #858585; 321 - font-size: 12px; 322 - } 3 + <head> 4 + <meta charset="utf-8"> 5 + <meta http-equiv="Content-Security-Policy" content="script-src 'self' 'unsafe-inline'; worker-src blob:;"> 6 + <meta name="viewport" content="width=device-width,user-scalable=no,initial-scale=1"> 7 + <title>Scripts Manager</title> 8 + <link rel="stylesheet" type="text/css" href="manager.css"> 323 9 324 - .result-data { 325 - background: #1e1e1e; 326 - padding: 8px; 327 - border-radius: 3px; 328 - font-family: 'Monaco', 'Menlo', 'Consolas', monospace; 329 - font-size: 12px; 330 - overflow-x: auto; 331 - white-space: pre-wrap; 332 - } 333 - 334 - .empty-state { 335 - color: #858585; 336 - text-align: center; 337 - padding: 40px 20px; 338 - font-size: 13px; 339 - } 340 - 341 - .console-output { 342 - margin-top: 12px; 343 - } 344 - 345 - .console-output h3 { 346 - font-size: 12px; 347 - color: #858585; 348 - margin-bottom: 8px; 349 - } 350 - 351 - .console-line { 352 - font-family: 'Monaco', 'Menlo', 'Consolas', monospace; 353 - font-size: 11px; 354 - padding: 2px 0; 355 - } 356 - 357 - .console-line.log { 358 - color: #d4d4d4; 359 - } 360 - 361 - .console-line.error { 362 - color: #f48771; 10 + <!-- Import map for resolving bare module specifiers --> 11 + <script type="importmap"> 12 + { 13 + "imports": { 14 + "lit": "peek://node_modules/lit/index.js", 15 + "lit/": "peek://node_modules/lit/", 16 + "lit-html": "peek://node_modules/lit-html/lit-html.js", 17 + "lit-html/": "peek://node_modules/lit-html/", 18 + "lit-element": "peek://node_modules/lit-element/lit-element.js", 19 + "lit-element/": "peek://node_modules/lit-element/", 20 + "@lit/reactive-element": "peek://node_modules/@lit/reactive-element/reactive-element.js", 21 + "@lit/reactive-element/": "peek://node_modules/@lit/reactive-element/" 22 + } 363 23 } 24 + </script> 364 25 365 - .console-line.warn { 366 - color: #dcdcaa; 367 - } 368 - </style> 369 - </head> 370 - <body> 371 - <div class="container"> 372 - <!-- Left Panel: Scripts List --> 373 - <div class="scripts-list"> 374 - <div class="scripts-header"> 375 - <h1>Scripts</h1> 376 - <button class="new-script-btn" id="newScriptBtn">+ New Script</button> 26 + <!-- Import peek-components --> 27 + <script type="module"> 28 + import 'peek://app/components/peek-input.js'; 29 + import 'peek://app/components/peek-button.js'; 30 + </script> 31 + </head> 32 + <body> 33 + <div class="container"> 34 + <!-- Left Panel: Scripts List --> 35 + <div class="scripts-list"> 36 + <div class="scripts-header"> 37 + <h1>Scripts</h1> 38 + <peek-button id="newScriptBtn" variant="primary" style="width: 100%;">+ New Script</peek-button> 39 + </div> 40 + <div class="scripts-items" id="scriptsList"> 41 + <div class="empty-state">No scripts yet. Click "+ New Script" to create one.</div> 42 + </div> 377 43 </div> 378 - <div class="scripts-items" id="scriptsList"> 379 - <div class="empty-state">No scripts yet. Click "+ New Script" to create one.</div> 380 - </div> 381 - </div> 382 44 383 - <!-- Center Panel: Editor --> 384 - <div class="editor-panel"> 385 - <div class="editor-header"> 386 - <div class="editor-form" id="editorForm"> 387 - <div class="form-group"> 388 - <label>Name</label> 389 - <input type="text" id="scriptName" placeholder="My Script"> 390 - </div> 391 - <div style="display: flex; gap: 12px;"> 392 - <div class="form-group" style="flex: 1;"> 393 - <label>Match Pattern</label> 394 - <input type="text" id="matchPattern" placeholder="https://example.com/*"> 45 + <!-- Center Panel: Editor --> 46 + <div class="editor-panel"> 47 + <div class="editor-header"> 48 + <div class="editor-form" id="editorForm"> 49 + <div class="form-group"> 50 + <label>Name</label> 51 + <peek-input id="scriptName" placeholder="My Script"></peek-input> 395 52 </div> 396 - <div class="form-group" style="width: 150px;"> 397 - <label>Run At</label> 398 - <select id="runAt"> 399 - <option value="document-start">Document Start</option> 400 - <option value="document-end" selected>Document End</option> 401 - <option value="document-idle">Document Idle</option> 402 - </select> 53 + <div class="form-row"> 54 + <div class="form-group flex-1"> 55 + <label>Match Pattern</label> 56 + <peek-input id="matchPattern" placeholder="https://example.com/*"></peek-input> 57 + </div> 58 + <div class="form-group w-150"> 59 + <label>Run At</label> 60 + <select id="runAt"> 61 + <option value="document-start">Document Start</option> 62 + <option value="document-end" selected>Document End</option> 63 + <option value="document-idle">Document Idle</option> 64 + </select> 65 + </div> 403 66 </div> 404 - </div> 405 - <div class="form-group"> 406 - <label>Description</label> 407 - <input type="text" id="scriptDescription" placeholder="What does this script do?"> 67 + <div class="form-group"> 68 + <label>Description</label> 69 + <peek-input id="scriptDescription" placeholder="What does this script do?"></peek-input> 70 + </div> 408 71 </div> 409 72 </div> 410 - </div> 411 - <div class="editor-content"> 412 - <textarea class="code-editor" id="codeEditor" placeholder="// Your script here&#10;const h1 = document.querySelector('h1');&#10;return { title: h1?.textContent || 'No h1 found' };"></textarea> 73 + <div class="editor-content"> 74 + <textarea class="code-editor" id="codeEditor" placeholder="// Your script here&#10;const h1 = document.querySelector('h1');&#10;return { title: h1?.textContent || 'No h1 found' };"></textarea> 75 + </div> 76 + <div class="editor-actions"> 77 + <peek-button id="saveBtn" variant="primary">Save</peek-button> 78 + <peek-button id="revertBtn" variant="ghost">Revert</peek-button> 79 + <peek-button id="deleteBtn" variant="danger">Delete</peek-button> 80 + </div> 413 81 </div> 414 - <div class="editor-actions"> 415 - <button class="btn btn-primary" id="saveBtn">Save</button> 416 - <button class="btn btn-secondary" id="revertBtn">Revert</button> 417 - <button class="btn btn-danger" id="deleteBtn">Delete</button> 418 - </div> 419 - </div> 420 82 421 - <!-- Right Panel: Preview --> 422 - <div class="preview-panel"> 423 - <div class="preview-header"> 424 - <h2>Test & Preview</h2> 425 - <div class="test-url-group"> 426 - <input type="text" class="test-url-input" id="testUrl" placeholder="https://example.com"> 427 - <button class="test-btn" id="testBtn">Test Script</button> 83 + <!-- Right Panel: Preview --> 84 + <div class="preview-panel"> 85 + <div class="preview-header"> 86 + <h2>Test & Preview</h2> 87 + <div class="test-url-group"> 88 + <peek-input id="testUrl" placeholder="https://example.com"></peek-input> 89 + <peek-button id="testBtn" variant="primary" style="width: 100%;">Test Script</peek-button> 90 + </div> 428 91 </div> 429 - </div> 430 - <div class="preview-content" id="previewContent"> 431 - <div class="empty-state"> 432 - Enter a test URL and click "Test Script" to see results. 92 + <div class="preview-content" id="previewContent"> 93 + <div class="empty-state"> 94 + Enter a test URL and click "Test Script" to see results. 95 + </div> 433 96 </div> 434 97 </div> 435 98 </div> 436 - </div> 437 99 438 - <script type="module" src="./manager.js"></script> 439 - </body> 100 + <script type="module" src="./manager.js"></script> 101 + </body> 440 102 </html>
+10 -10
extensions/scripts/manager.js
··· 273 273 } 274 274 275 275 testBtn.disabled = true; 276 - testBtn.textContent = 'Running...'; 276 + testBtn.loading = true; 277 277 278 278 try { 279 279 // Use current form values (not saved script) ··· 296 296 showPreviewError(error.message); 297 297 } finally { 298 298 testBtn.disabled = false; 299 - testBtn.textContent = 'Test Script'; 299 + testBtn.loading = false; 300 300 } 301 301 } 302 302 ··· 335 335 if (result.status === 'success') { 336 336 html = ` 337 337 <div class="result-box"> 338 - <div class="result-status success">✓ Success</div> 338 + <div class="result-status success">Success</div> 339 339 <div class="result-time">Execution time: ${result.executionTime}ms</div> 340 340 ${result.result !== undefined ? ` 341 - <div style="margin-top: 12px;"> 342 - <strong style="font-size: 12px; color: #858585;">Result:</strong> 341 + <div> 342 + <div class="result-label">Result:</div> 343 343 <div class="result-data">${JSON.stringify(result.result, null, 2)}</div> 344 344 </div> 345 345 ` : ''} ··· 356 356 } else if (result.status === 'error') { 357 357 html = ` 358 358 <div class="result-box"> 359 - <div class="result-status error">✗ Error</div> 359 + <div class="result-status error">Error</div> 360 360 <div class="result-data">${escapeHtml(result.error)}</div> 361 361 ${result.stack ? ` 362 - <div style="margin-top: 8px; font-size: 11px; color: #858585;"> 362 + <div class="result-stack"> 363 363 <strong>Stack:</strong> 364 - <pre style="margin-top: 4px;">${escapeHtml(result.stack)}</pre> 364 + <pre>${escapeHtml(result.stack)}</pre> 365 365 </div> 366 366 ` : ''} 367 367 </div> ··· 369 369 } else if (result.status === 'skipped') { 370 370 html = ` 371 371 <div class="result-box"> 372 - <div class="result-status" style="color: #dcdcaa;">⊘ Skipped</div> 373 - <div style="font-size: 12px; color: #858585;">${escapeHtml(result.reason)}</div> 372 + <div class="result-status skipped">Skipped</div> 373 + <div class="result-reason">${escapeHtml(result.reason)}</div> 374 374 </div> 375 375 `; 376 376 }