viainti-chart 1.0.1 → 1.0.3

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 CHANGED
@@ -66,11 +66,34 @@ export function Spark() {
66
66
  }
67
67
  ```
68
68
 
69
+ ### Compact chart (sin métricas)
70
+
71
+ ```tsx
72
+ import { TradingViewChart, OHLCData } from 'viainti-chart';
73
+
74
+ const cached: OHLCData[] = [...];
75
+
76
+ export function InlineCard() {
77
+ return (
78
+ <TradingViewChart
79
+ data={cached}
80
+ symbol="BTC/USDT"
81
+ showStats={false}
82
+ showHeaderStats={false}
83
+ />
84
+ );
85
+ }
86
+ ```
87
+
88
+ `showStats={false}` elimina las tarjetas de “Trading range / Avg volume / Volatility” y `showHeaderStats={false}` oculta la banda superior (símbolo + O/H/L/C/V) y el footer “Feed Binance Composite”. Para verlo en vivo ejecuta `npm run dev` y abre `http://localhost:5173?mode=simple`; cambia a `?mode=advanced` para volver al layout completo.
89
+
69
90
  ## API
70
91
 
71
92
  ### `<TradingViewChart />`
72
93
  - `data: OHLCData[]` – candles with `open`, `high`, `low`, `close`, optional `volume` & `timestamp`.
73
94
  - `symbol?: string` – label displayed in the header (default `VIA/USDT`).
95
+ - `showStats?: boolean` – toggle the lower metric cards (defaults to `true`).
96
+ - `showHeaderStats?: boolean` – hides the hero ribbon/footer for an ultra-compact mode when set to `false`.
74
97
 
75
98
  ### `<Chart />`
76
99
  - `data: OHLCData[]`
@@ -130,6 +153,8 @@ npm publish --access public
130
153
  ```
131
154
 
132
155
  > If `npm publish` returns `Access token expired or revoked`, run `npm logout`, then authenticate again with `npm login` (or `npm adduser`) before retrying. Use `npm whoami` to confirm the session is active and `npm config get registry` to ensure you're pushing to `https://registry.npmjs.org/`.
156
+ >
157
+ > Para etiquetar la build compacta, publica normalmente (tag `latest`) y luego añade un dist-tag separado, por ejemplo: `npm dist-tag add viainti-chart@1.0.3 simple`. Así podrás instalarla con `npm install viainti-chart@simple` en proyectos que necesiten el modo reducido por defecto.
133
158
 
134
159
  ## Credits
135
160
 
package/dist/index.cjs CHANGED
@@ -2156,7 +2156,7 @@ const computeVisibleWindow = (dataset, chartWidth, timeframe, zoomLevel, panOffs
2156
2156
  }
2157
2157
  };
2158
2158
  };
2159
- const TradingViewChart = ({ data, symbol = 'BTC/USDT', onTimeframeChange }) => {
2159
+ const TradingViewChart = ({ data, symbol = 'BTC/USDT', onTimeframeChange, showStats = true, showHeaderStats = true }) => {
2160
2160
  const chartRef = React.useRef(null);
2161
2161
  const volumeRef = React.useRef(null);
2162
2162
  const gridRef = React.useRef(null);
@@ -2438,12 +2438,13 @@ const TradingViewChart = ({ data, symbol = 'BTC/USDT', onTimeframeChange }) => {
2438
2438
  const iconBaseColor = '#f8fafc';
2439
2439
  const leftRailBaseBg = themePreset === 'light' ? '#0f172a' : activeTheme.panelBg;
2440
2440
  const strings = React.useMemo(() => UI_TEXT[language] ?? UI_TEXT.en, [language]);
2441
+ const compactHeader = !showHeaderStats;
2441
2442
  const [isFullscreen, setIsFullscreen] = React.useState(false);
2442
2443
  const [selectedCandleIndex, setSelectedCandleIndex] = React.useState(null);
2443
2444
  const [seriesType, setSeriesType] = React.useState('candles');
2444
2445
  const [showSeriesMenu, setShowSeriesMenu] = React.useState(false);
2445
2446
  const [isSeriesLoading, setIsSeriesLoading] = React.useState(false);
2446
- const [showQuickTips, setShowQuickTips] = React.useState(true);
2447
+ const [showQuickTips, setShowQuickTips] = React.useState(showHeaderStats);
2447
2448
  const [toastMessage, setToastMessage] = React.useState(null);
2448
2449
  const [showNoteModal, setShowNoteModal] = React.useState(false);
2449
2450
  const [pendingNotePoint, setPendingNotePoint] = React.useState(null);
@@ -3224,6 +3225,87 @@ const TradingViewChart = ({ data, symbol = 'BTC/USDT', onTimeframeChange }) => {
3224
3225
  { value: 'columns', label: 'Columnas', icon: seriesIconMap.columns },
3225
3226
  { value: 'high-low', label: 'High/Low', icon: seriesIconMap['high-low'] }
3226
3227
  ];
3228
+ const headerButtons = (React.createElement(React.Fragment, null,
3229
+ React.createElement("button", { onClick: () => setShowSeriesMenu(!showSeriesMenu), style: {
3230
+ width: '38px',
3231
+ height: '38px',
3232
+ borderRadius: '999px',
3233
+ border: `1px solid ${showSeriesMenu ? activeTheme.accent : iconBaseBg}`,
3234
+ background: showSeriesMenu ? activeTheme.accent : iconBaseBg,
3235
+ color: iconBaseColor,
3236
+ display: 'flex',
3237
+ alignItems: 'center',
3238
+ justifyContent: 'center',
3239
+ cursor: 'pointer',
3240
+ transition: 'all 0.2s'
3241
+ }, title: strings.buttons.series, "aria-label": strings.buttons.series }, seriesIconMap[seriesType] ?? React.createElement(BsGraphUp, null)),
3242
+ React.createElement("button", { onClick: toggleIndicatorsPanel, style: {
3243
+ background: showIndicatorsPanel ? '#2563eb' : 'rgba(15,23,42,0.6)',
3244
+ color: '#e2e8f0',
3245
+ border: '1px solid #1f2937',
3246
+ borderRadius: '999px',
3247
+ padding: '8px 14px',
3248
+ fontSize: '12px',
3249
+ fontWeight: 600,
3250
+ cursor: 'pointer',
3251
+ transition: 'all 0.2s'
3252
+ } }, strings.buttons.indicators),
3253
+ React.createElement("button", { onClick: () => setShowConfigPanel(!showConfigPanel), style: {
3254
+ width: '38px',
3255
+ height: '38px',
3256
+ borderRadius: '999px',
3257
+ border: `1px solid ${showConfigPanel ? activeTheme.accent : iconBaseBg}`,
3258
+ background: showConfigPanel ? activeTheme.accent : iconBaseBg,
3259
+ color: iconBaseColor,
3260
+ display: 'flex',
3261
+ alignItems: 'center',
3262
+ justifyContent: 'center',
3263
+ cursor: 'pointer',
3264
+ transition: 'all 0.2s'
3265
+ }, title: strings.buttons.config, "aria-label": strings.buttons.config },
3266
+ React.createElement(BsGear, null)),
3267
+ React.createElement("button", { onClick: () => setIsFullscreen(prev => !prev), style: {
3268
+ width: '38px',
3269
+ height: '38px',
3270
+ borderRadius: '999px',
3271
+ border: `1px solid ${isFullscreen ? activeTheme.accent : iconBaseBg}`,
3272
+ background: isFullscreen ? activeTheme.accent : iconBaseBg,
3273
+ color: iconBaseColor,
3274
+ display: 'flex',
3275
+ alignItems: 'center',
3276
+ justifyContent: 'center',
3277
+ cursor: 'pointer',
3278
+ transition: 'all 0.2s'
3279
+ }, title: isFullscreen ? strings.buttons.fullscreenExit : strings.buttons.fullscreenEnter, "aria-label": isFullscreen ? strings.buttons.fullscreenExit : strings.buttons.fullscreenEnter },
3280
+ React.createElement(BsArrowsFullscreen, null)),
3281
+ React.createElement("button", { onClick: takeScreenshot, style: {
3282
+ width: '38px',
3283
+ height: '38px',
3284
+ borderRadius: '999px',
3285
+ border: `1px solid ${iconBaseBg}`,
3286
+ background: iconBaseBg,
3287
+ color: iconBaseColor,
3288
+ display: 'flex',
3289
+ alignItems: 'center',
3290
+ justifyContent: 'center',
3291
+ cursor: 'pointer',
3292
+ transition: 'all 0.2s'
3293
+ }, title: strings.buttons.screenshot, "aria-label": strings.buttons.screenshot },
3294
+ React.createElement(BsCamera, null)),
3295
+ showHeaderStats && (React.createElement("button", { onClick: () => setShowQuickTips(prev => !prev), style: {
3296
+ width: '38px',
3297
+ height: '38px',
3298
+ borderRadius: '999px',
3299
+ border: `1px solid ${showQuickTips ? activeTheme.accent : iconBaseBg}`,
3300
+ background: showQuickTips ? activeTheme.accent : iconBaseBg,
3301
+ color: iconBaseColor,
3302
+ display: 'flex',
3303
+ alignItems: 'center',
3304
+ justifyContent: 'center',
3305
+ cursor: 'pointer',
3306
+ transition: 'all 0.2s'
3307
+ }, title: strings.buttons.help, "aria-label": strings.buttons.help },
3308
+ React.createElement(BsQuestionCircle, null)))));
3227
3309
  const cursorCss = isDraggingRef.current
3228
3310
  ? 'grabbing'
3229
3311
  : cursorType === 'cross'
@@ -3252,13 +3334,12 @@ const TradingViewChart = ({ data, symbol = 'BTC/USDT', onTimeframeChange }) => {
3252
3334
  background: `linear-gradient(120deg, ${activeTheme.heroFrom} 0%, ${activeTheme.heroTo} 100%)`,
3253
3335
  borderBottom: `1px solid ${activeTheme.panelBorder}`,
3254
3336
  display: 'flex',
3255
- flexWrap: 'wrap',
3337
+ flexDirection: 'column',
3256
3338
  gap: isMobile ? '12px' : '16px',
3257
- alignItems: 'center',
3258
3339
  padding: isMobile ? '12px 16px' : '16px 20px',
3259
3340
  boxShadow: elevatedShadow
3260
3341
  }, initial: { opacity: 0, y: -15 }, animate: { opacity: 1, y: 0 }, transition: { duration: 0.3 } },
3261
- React.createElement("div", { style: { display: 'flex', flexWrap: 'wrap', gap: '12px', alignItems: 'center', minWidth: 0 } },
3342
+ showHeaderStats && (React.createElement("div", { style: { display: 'flex', flexWrap: 'wrap', gap: '12px', alignItems: 'center', minWidth: 0 } },
3262
3343
  React.createElement("div", { style: { background: activeTheme.cardBg, border: `1px solid ${activeTheme.cardBorder}`, borderRadius: '14px', padding: '10px 16px', minWidth: '160px', color: activeTheme.textPrimary } },
3263
3344
  React.createElement("div", { style: { fontSize: '11px', textTransform: 'uppercase', letterSpacing: '0.08em', color: activeTheme.textSecondary, marginBottom: '4px' } }, strings.symbolLabel),
3264
3345
  React.createElement("div", { style: { display: 'flex', alignItems: 'center', justifyContent: 'space-between', color: activeTheme.textPrimary, fontWeight: 600, gap: '10px' } },
@@ -3290,150 +3371,118 @@ const TradingViewChart = ({ data, symbol = 'BTC/USDT', onTimeframeChange }) => {
3290
3371
  { label: 'V', value: referenceCandle.volume ?? 0 }
3291
3372
  ].map(item => (React.createElement("div", { key: item.label, style: { display: 'flex', flexDirection: 'column', minWidth: '50px' } },
3292
3373
  React.createElement("span", { style: { fontSize: '10px', letterSpacing: '0.08em', textTransform: 'uppercase' } }, item.label),
3293
- React.createElement("span", { style: { color: '#e2e8f0', fontWeight: 600 } }, item.value.toFixed(2)))))))),
3294
- React.createElement("div", { style: {
3374
+ React.createElement("span", { style: { color: '#e2e8f0', fontWeight: 600 } }, item.value.toFixed(2))))))))),
3375
+ compactHeader ? (React.createElement("div", { style: {
3376
+ width: '100%',
3295
3377
  display: 'flex',
3378
+ flexWrap: isMobile ? 'wrap' : 'nowrap',
3296
3379
  alignItems: 'center',
3297
- gap: '12px',
3298
- padding: '10px 14px',
3299
- background: activeTheme.panelBg,
3300
- borderRadius: '16px',
3301
- border: `1px solid ${activeTheme.panelBorder}`,
3302
- overflowX: 'auto'
3380
+ gap: isMobile ? '12px' : '16px'
3303
3381
  } },
3304
- React.createElement("div", { style: { display: 'flex', alignItems: 'center', gap: '6px', whiteSpace: 'nowrap' } },
3305
- React.createElement("span", { style: { fontSize: '10px', letterSpacing: '0.08em', textTransform: 'uppercase', color: '#94a3b8' } }, strings.timeframeTitle),
3306
- React.createElement("span", { style: { fontSize: '11px', color: '#f8fafc', fontWeight: 600, padding: '2px 8px', borderRadius: '999px', background: 'rgba(37,99,235,0.25)', border: '1px solid rgba(37,99,235,0.6)' } }, timeframe)),
3307
- React.createElement("div", { style: { display: 'flex', gap: '6px', flex: 1, minWidth: 0, overflowX: 'auto', paddingBottom: '4px' } }, ['1m', '3m', '5m', '15m', '30m', '1h', '4h'].map(tf => (React.createElement("button", { key: tf, onClick: () => handleTimeframeChange(tf), style: {
3308
- background: timeframe === tf ? activeTheme.accent : activeTheme.panelBg,
3309
- color: timeframe === tf ? '#f8fafc' : activeTheme.textSecondary,
3310
- border: `1px solid ${timeframe === tf ? activeTheme.accent : activeTheme.panelBorder}`,
3311
- borderRadius: '10px',
3312
- padding: '6px 12px',
3313
- fontSize: '12px',
3314
- fontWeight: 600,
3315
- cursor: 'pointer',
3316
- transition: 'all 0.2s',
3317
- flex: '0 0 auto',
3318
- whiteSpace: 'nowrap'
3319
- } }, tf)))),
3320
- React.createElement("div", { style: { display: 'flex', alignItems: 'center', gap: '6px', fontSize: '12px', color: '#cbd5f5', whiteSpace: 'nowrap', flexShrink: 0 } },
3321
- React.createElement(BsClockHistory, null),
3322
- React.createElement("span", null,
3323
- strings.axis.time,
3324
- ": ",
3325
- currentTimeLabel)),
3326
- React.createElement("select", { value: timeframe, onChange: (e) => handleTimeframeChange(e.target.value), style: {
3327
- background: 'rgba(15,23,42,0.8)',
3328
- color: '#e2e8f0',
3329
- border: '1px solid #1f2937',
3330
- padding: '10px 36px 10px 12px',
3331
- borderRadius: '12px',
3332
- cursor: 'pointer',
3333
- fontSize: '12px',
3334
- fontWeight: 600,
3335
- appearance: 'none',
3336
- backgroundImage: `url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' fill='none' viewBox='0 0 20 20'%3e%3cpath stroke='%2394a3b8' stroke-linecap='round' stroke-linejoin='round' stroke-width='1.5' d='m6 8 4 4 4-4'/%3e%3c/svg%3e")`,
3337
- backgroundPosition: 'right 10px center',
3338
- backgroundRepeat: 'no-repeat',
3339
- backgroundSize: '14px',
3340
- minWidth: '120px',
3341
- flexShrink: 0
3342
- } },
3343
- React.createElement("option", { value: "1m" }, "1m"),
3344
- React.createElement("option", { value: "3m" }, "3m"),
3345
- React.createElement("option", { value: "5m" }, "5m"),
3346
- React.createElement("option", { value: "15m" }, "15m"),
3347
- React.createElement("option", { value: "30m" }, "30m"),
3348
- React.createElement("option", { value: "1h" }, "1h"),
3349
- React.createElement("option", { value: "4h" }, "4h"),
3350
- React.createElement("option", { value: "12h" }, "12h"),
3351
- React.createElement("option", { value: "1D" }, "1D"),
3352
- React.createElement("option", { value: "3D" }, "3D"),
3353
- React.createElement("option", { value: "1W" }, "1W"),
3354
- React.createElement("option", { value: "1M" }, "1M"))),
3355
- React.createElement("div", { style: { marginLeft: 'auto', display: 'flex', flexWrap: 'wrap', gap: '8px', alignItems: 'center' } },
3356
- React.createElement("button", { onClick: () => setShowSeriesMenu(!showSeriesMenu), style: {
3357
- width: '38px',
3358
- height: '38px',
3359
- borderRadius: '999px',
3360
- border: `1px solid ${showSeriesMenu ? activeTheme.accent : iconBaseBg}`,
3361
- background: showSeriesMenu ? activeTheme.accent : iconBaseBg,
3362
- color: iconBaseColor,
3382
+ React.createElement("div", { style: {
3363
3383
  display: 'flex',
3364
3384
  alignItems: 'center',
3365
- justifyContent: 'center',
3366
- cursor: 'pointer',
3367
- transition: 'all 0.2s'
3368
- }, title: strings.buttons.series, "aria-label": strings.buttons.series }, seriesIconMap[seriesType] ?? React.createElement(BsGraphUp, null)),
3369
- React.createElement("button", { onClick: toggleIndicatorsPanel, style: {
3370
- background: showIndicatorsPanel ? '#2563eb' : 'rgba(15,23,42,0.6)',
3371
- color: '#e2e8f0',
3372
- border: '1px solid #1f2937',
3373
- borderRadius: '999px',
3385
+ gap: '10px',
3374
3386
  padding: '8px 14px',
3375
- fontSize: '12px',
3376
- fontWeight: 600,
3377
- cursor: 'pointer',
3378
- transition: 'all 0.2s'
3379
- } }, strings.buttons.indicators),
3380
- React.createElement("button", { onClick: () => setShowConfigPanel(!showConfigPanel), style: {
3381
- width: '38px',
3382
- height: '38px',
3383
- borderRadius: '999px',
3384
- border: `1px solid ${showConfigPanel ? activeTheme.accent : iconBaseBg}`,
3385
- background: showConfigPanel ? activeTheme.accent : iconBaseBg,
3386
- color: iconBaseColor,
3387
- display: 'flex',
3388
- alignItems: 'center',
3389
- justifyContent: 'center',
3390
- cursor: 'pointer',
3391
- transition: 'all 0.2s'
3392
- }, title: strings.buttons.config, "aria-label": strings.buttons.config },
3393
- React.createElement(BsGear, null)),
3394
- React.createElement("button", { onClick: () => setIsFullscreen(prev => !prev), style: {
3395
- width: '38px',
3396
- height: '38px',
3397
- borderRadius: '999px',
3398
- border: `1px solid ${isFullscreen ? activeTheme.accent : iconBaseBg}`,
3399
- background: isFullscreen ? activeTheme.accent : iconBaseBg,
3400
- color: iconBaseColor,
3401
- display: 'flex',
3402
- alignItems: 'center',
3403
- justifyContent: 'center',
3404
- cursor: 'pointer',
3405
- transition: 'all 0.2s'
3406
- }, title: isFullscreen ? strings.buttons.fullscreenExit : strings.buttons.fullscreenEnter, "aria-label": isFullscreen ? strings.buttons.fullscreenExit : strings.buttons.fullscreenEnter },
3407
- React.createElement(BsArrowsFullscreen, null)),
3408
- React.createElement("button", { onClick: takeScreenshot, style: {
3409
- width: '38px',
3410
- height: '38px',
3411
- borderRadius: '999px',
3412
- border: `1px solid ${iconBaseBg}`,
3413
- background: iconBaseBg,
3414
- color: iconBaseColor,
3415
- display: 'flex',
3416
- alignItems: 'center',
3417
- justifyContent: 'center',
3418
- cursor: 'pointer',
3419
- transition: 'all 0.2s'
3420
- }, title: strings.buttons.screenshot, "aria-label": strings.buttons.screenshot },
3421
- React.createElement(BsCamera, null)),
3422
- React.createElement("button", { onClick: () => setShowQuickTips(prev => !prev), style: {
3423
- width: '38px',
3424
- height: '38px',
3425
- borderRadius: '999px',
3426
- border: `1px solid ${showQuickTips ? activeTheme.accent : iconBaseBg}`,
3427
- background: showQuickTips ? activeTheme.accent : iconBaseBg,
3428
- color: iconBaseColor,
3387
+ background: activeTheme.panelBg,
3388
+ borderRadius: '16px',
3389
+ border: `1px solid ${activeTheme.panelBorder}`,
3390
+ flex: 1,
3391
+ minWidth: isMobile ? '100%' : '320px'
3392
+ } },
3393
+ React.createElement("span", { style: { fontSize: '10px', letterSpacing: '0.08em', textTransform: 'uppercase', color: '#94a3b8' } }, strings.timeframeTitle),
3394
+ React.createElement("select", { value: timeframe, onChange: (e) => handleTimeframeChange(e.target.value), style: {
3395
+ background: 'rgba(15,23,42,0.8)',
3396
+ color: '#e2e8f0',
3397
+ border: '1px solid #1f2937',
3398
+ padding: '8px 32px 8px 12px',
3399
+ borderRadius: '12px',
3400
+ cursor: 'pointer',
3401
+ fontSize: '12px',
3402
+ fontWeight: 600,
3403
+ appearance: 'none',
3404
+ backgroundImage: `url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' fill='none' viewBox='0 0 20 20'%3e%3cpath stroke='%2394a3b8' stroke-linecap='round' stroke-linejoin='round' stroke-width='1.5' d='m6 8 4 4 4-4'/%3e%3c/svg%3e")`,
3405
+ backgroundPosition: 'right 10px center',
3406
+ backgroundRepeat: 'no-repeat',
3407
+ backgroundSize: '14px',
3408
+ minWidth: '140px'
3409
+ } },
3410
+ React.createElement("option", { value: "1m" }, "1m"),
3411
+ React.createElement("option", { value: "3m" }, "3m"),
3412
+ React.createElement("option", { value: "5m" }, "5m"),
3413
+ React.createElement("option", { value: "15m" }, "15m"),
3414
+ React.createElement("option", { value: "30m" }, "30m"),
3415
+ React.createElement("option", { value: "1h" }, "1h"),
3416
+ React.createElement("option", { value: "4h" }, "4h"),
3417
+ React.createElement("option", { value: "12h" }, "12h"),
3418
+ React.createElement("option", { value: "1D" }, "1D"),
3419
+ React.createElement("option", { value: "3D" }, "3D"),
3420
+ React.createElement("option", { value: "1W" }, "1W"),
3421
+ React.createElement("option", { value: "1M" }, "1M"))),
3422
+ React.createElement("div", { style: { marginLeft: isMobile ? 0 : 'auto', display: 'flex', flexWrap: isMobile ? 'wrap' : 'nowrap', gap: '8px', alignItems: 'center' } }, headerButtons))) : (React.createElement(React.Fragment, null,
3423
+ React.createElement("div", { style: {
3429
3424
  display: 'flex',
3430
3425
  alignItems: 'center',
3431
- justifyContent: 'center',
3432
- cursor: 'pointer',
3433
- transition: 'all 0.2s'
3434
- }, title: strings.buttons.help, "aria-label": strings.buttons.help },
3435
- React.createElement(BsQuestionCircle, null)))),
3436
- derivedStats && (React.createElement("div", { style: { padding: '16px 20px 0', background: activeTheme.panelBg, borderBottom: `1px solid ${activeTheme.panelBorder}` } },
3426
+ gap: '12px',
3427
+ padding: '10px 14px',
3428
+ background: activeTheme.panelBg,
3429
+ borderRadius: '16px',
3430
+ border: `1px solid ${activeTheme.panelBorder}`,
3431
+ overflowX: 'auto'
3432
+ } },
3433
+ React.createElement("div", { style: { display: 'flex', alignItems: 'center', gap: '6px', whiteSpace: 'nowrap' } },
3434
+ React.createElement("span", { style: { fontSize: '10px', letterSpacing: '0.08em', textTransform: 'uppercase', color: '#94a3b8' } }, strings.timeframeTitle),
3435
+ React.createElement("span", { style: { fontSize: '11px', color: '#f8fafc', fontWeight: 600, padding: '2px 8px', borderRadius: '999px', background: 'rgba(37,99,235,0.25)', border: '1px solid rgba(37,99,235,0.6)' } }, timeframe)),
3436
+ React.createElement("div", { style: { display: 'flex', gap: '6px', flex: 1, minWidth: 0, overflowX: 'auto', paddingBottom: '4px' } }, ['1m', '3m', '5m', '15m', '30m', '1h', '4h'].map(tf => (React.createElement("button", { key: tf, onClick: () => handleTimeframeChange(tf), style: {
3437
+ background: timeframe === tf ? activeTheme.accent : activeTheme.panelBg,
3438
+ color: timeframe === tf ? '#f8fafc' : activeTheme.textSecondary,
3439
+ border: `1px solid ${timeframe === tf ? activeTheme.accent : activeTheme.panelBorder}`,
3440
+ borderRadius: '10px',
3441
+ padding: '6px 12px',
3442
+ fontSize: '12px',
3443
+ fontWeight: 600,
3444
+ cursor: 'pointer',
3445
+ transition: 'all 0.2s',
3446
+ flex: '0 0 auto',
3447
+ whiteSpace: 'nowrap'
3448
+ } }, tf)))),
3449
+ React.createElement("div", { style: { display: 'flex', alignItems: 'center', gap: '6px', fontSize: '12px', color: '#cbd5f5', whiteSpace: 'nowrap', flexShrink: 0 } },
3450
+ React.createElement(BsClockHistory, null),
3451
+ React.createElement("span", null,
3452
+ strings.axis.time,
3453
+ ": ",
3454
+ currentTimeLabel)),
3455
+ React.createElement("select", { value: timeframe, onChange: (e) => handleTimeframeChange(e.target.value), style: {
3456
+ background: 'rgba(15,23,42,0.8)',
3457
+ color: '#e2e8f0',
3458
+ border: '1px solid #1f2937',
3459
+ padding: '10px 36px 10px 12px',
3460
+ borderRadius: '12px',
3461
+ cursor: 'pointer',
3462
+ fontSize: '12px',
3463
+ fontWeight: 600,
3464
+ appearance: 'none',
3465
+ backgroundImage: `url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' fill='none' viewBox='0 0 20 20'%3e%3cpath stroke='%2394a3b8' stroke-linecap='round' stroke-linejoin='round' stroke-width='1.5' d='m6 8 4 4 4-4'/%3e%3c/svg%3e")`,
3466
+ backgroundPosition: 'right 10px center',
3467
+ backgroundRepeat: 'no-repeat',
3468
+ backgroundSize: '14px',
3469
+ minWidth: '120px',
3470
+ flexShrink: 0
3471
+ } },
3472
+ React.createElement("option", { value: "1m" }, "1m"),
3473
+ React.createElement("option", { value: "3m" }, "3m"),
3474
+ React.createElement("option", { value: "5m" }, "5m"),
3475
+ React.createElement("option", { value: "15m" }, "15m"),
3476
+ React.createElement("option", { value: "30m" }, "30m"),
3477
+ React.createElement("option", { value: "1h" }, "1h"),
3478
+ React.createElement("option", { value: "4h" }, "4h"),
3479
+ React.createElement("option", { value: "12h" }, "12h"),
3480
+ React.createElement("option", { value: "1D" }, "1D"),
3481
+ React.createElement("option", { value: "3D" }, "3D"),
3482
+ React.createElement("option", { value: "1W" }, "1W"),
3483
+ React.createElement("option", { value: "1M" }, "1M"))),
3484
+ React.createElement("div", { style: { marginLeft: 'auto', display: 'flex', flexWrap: 'wrap', gap: '8px', alignItems: 'center' } }, headerButtons)))),
3485
+ showStats && derivedStats && (React.createElement("div", { style: { padding: '16px 20px 0', background: activeTheme.panelBg, borderBottom: `1px solid ${activeTheme.panelBorder}` } },
3437
3486
  React.createElement("div", { style: { display: 'grid', gridTemplateColumns: 'repeat(auto-fit, minmax(180px, 1fr))', gap: '12px' } },
3438
3487
  React.createElement("div", { style: { ...metricCardStyle, background: activeTheme.cardBg, border: `1px solid ${activeTheme.cardBorder}` } },
3439
3488
  React.createElement("span", { style: { ...metricLabelStyle, color: activeTheme.textSecondary } }, "Trading range"),
@@ -3461,7 +3510,7 @@ const TradingViewChart = ({ data, symbol = 'BTC/USDT', onTimeframeChange }) => {
3461
3510
  "Latency ~",
3462
3511
  latencyMs,
3463
3512
  "ms"))))),
3464
- React.createElement(framerMotion.AnimatePresence, null, showQuickTips && (React.createElement(framerMotion.motion.div, { initial: { opacity: 0, y: -10 }, animate: { opacity: 1, y: 0 }, exit: { opacity: 0, y: -10 }, transition: { duration: 0.2 }, style: {
3513
+ React.createElement(framerMotion.AnimatePresence, null, showHeaderStats && showQuickTips && (React.createElement(framerMotion.motion.div, { initial: { opacity: 0, y: -10 }, animate: { opacity: 1, y: 0 }, exit: { opacity: 0, y: -10 }, transition: { duration: 0.2 }, style: {
3465
3514
  position: (isFullscreen ? 'fixed' : 'absolute'),
3466
3515
  top: isFullscreen ? 80 : 140,
3467
3516
  left: isFullscreen ? 80 : 140,
@@ -3793,7 +3842,7 @@ const TradingViewChart = ({ data, symbol = 'BTC/USDT', onTimeframeChange }) => {
3793
3842
  React.createElement("span", null, field.label),
3794
3843
  React.createElement("input", { type: "color", value: customTheme[field.key], onChange: (event) => handleCustomThemeChange(field.key, event.target.value), style: { width: '100%', height: '34px', border: 'none', cursor: 'pointer', borderRadius: '8px', background: 'transparent' } })))))),
3795
3844
  React.createElement("div", { style: { fontSize: '12px', color: activeTheme.textSecondary } }, strings.config.soon))),
3796
- React.createElement("div", { style: { padding: isMobile ? '8px 16px' : '10px 20px', background: activeTheme.panelBg, borderTop: `1px solid ${activeTheme.panelBorder}`, display: 'flex', flexWrap: 'wrap', gap: isMobile ? '12px' : '18px', fontSize: '10px', letterSpacing: '0.08em', textTransform: 'uppercase', color: activeTheme.textSecondary } },
3845
+ showHeaderStats && (React.createElement("div", { style: { padding: isMobile ? '8px 16px' : '10px 20px', background: activeTheme.panelBg, borderTop: `1px solid ${activeTheme.panelBorder}`, display: 'flex', flexWrap: 'wrap', gap: isMobile ? '12px' : '18px', fontSize: '10px', letterSpacing: '0.08em', textTransform: 'uppercase', color: activeTheme.textSecondary } },
3797
3846
  React.createElement("span", null,
3798
3847
  "Latency ",
3799
3848
  latencyMs,
@@ -3802,7 +3851,7 @@ const TradingViewChart = ({ data, symbol = 'BTC/USDT', onTimeframeChange }) => {
3802
3851
  "Session ",
3803
3852
  derivedStats?.session ?? 'Global'),
3804
3853
  React.createElement("span", null, "Feed Binance Composite"),
3805
- React.createElement("span", null, "Security AES-256"))));
3854
+ React.createElement("span", null, "Security AES-256")))));
3806
3855
  };
3807
3856
  var TradingViewChart_default = React.memo(TradingViewChart);
3808
3857