@tekkare/romulus 0.1.24 → 0.1.26
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/dist/module.json +1 -1
- package/dist/runtime/assets/styles/shell.css +1 -1
- package/dist/runtime/components/AppHeader.vue +13 -1
- package/dist/runtime/components/LineChart.vue +40 -0
- package/dist/runtime/utils/chart.d.ts +121 -23
- package/dist/runtime/utils/chart.js +60 -12
- package/dist/runtime/utils/format.d.ts +11 -0
- package/dist/runtime/utils/format.js +1 -0
- package/package.json +1 -1
package/dist/module.json
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
:root{--rm-shell-bg:#f9f9fa;--rm-shell-surface:#fff;--rm-shell-border:#dbdef0;--rm-shell-subtle:#f5f5f9;--rm-shell-text:#1e293b;--rm-shell-text-dark:#475569;--rm-shell-text-muted:#878ca6;--rm-shell-accent:#2017ad;--rm-shell-inset:8px;--rm-shell-radius:12px;--rm-bar-h:56px;--rm-nav-w:240px;--rm-nav-collapsed-w:64px;--rm-rail-w:56px;--rm-dots-image:url("data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAACgAAAAoCAYAAACM/rhtAAAAcUlEQVR42u3TwQmAMAxAUdfQfUoSZ3OBTNMFHEqLVBEtCB6M8B8EevwktOsAAACAl0SkNzNXtaw6zut7SikNYeJq2Hksh4gs27rG7ZH+eWA7bttigMC78x4TIdBbceX8fJKnkSL1s5RY8zBxAAAA+LUF0ula10BxVDoAAAAASUVORK5CYII=");--rm-dots-size:12px;--rm-dots-opacity:0.1}body.night{--rm-shell-bg:var(--bg-app);--rm-shell-surface:var(--bg-surface,#1a1a24);--rm-shell-border:var(--border-default);--rm-shell-subtle:var(--bg-subtle,#22222e);--rm-shell-text:var(--text-primary);--rm-shell-text-dark:var(--text-secondary);--rm-shell-text-muted:var(--text-muted);--rm-shell-accent:var(--color-primary);--rm-dots-opacity:0.06}.rm-shell{background:var(--rm-shell-bg);color:var(--rm-shell-text);font-family:var(--font-sans,"Figtree",sans-serif);inset:0;overflow:hidden;position:fixed}.rm-shell__dots{background-image:var(--rm-dots-image);background-repeat:repeat;background-size:var(--rm-dots-size) var(--rm-dots-size);inset:0;opacity:var(--rm-dots-opacity);pointer-events:none;position:absolute}.rm-shell__frame{border:1px solid var(--rm-shell-border);border-radius:var(--rm-shell-radius);display:flex;inset:var(--rm-shell-inset);overflow:hidden;position:absolute}.rm-shell__body{display:flex;flex:1;flex-direction:column;min-width:0}.rm-shell__main{flex:1;min-width:0;overflow-y:auto}.rm-sb{background:var(--rm-shell-surface);display:flex;flex-direction:column;flex-shrink:0;height:100%}.rm-sb--left{border-right:1px solid var(--rm-shell-border);position:relative;transition:width .2s;width:var(--rm-nav-w);z-index:200}.rm-sb--left.rm-sb--collapsed{width:var(--rm-nav-collapsed-w)}.rm-sb--right{border-left:1px solid var(--rm-shell-border);width:var(--rm-rail-w)}.rm-sb__header{align-items:center;border-bottom:1px solid var(--rm-shell-border);display:flex;flex-shrink:0;gap:8px;height:var(--rm-bar-h);padding:0 16px}.rm-sb--collapsed .rm-sb__header{justify-content:center;padding:0}.rm-sb__logo{align-items:center;color:var(--rm-shell-text);display:flex;flex:1;font-size:20px;font-weight:700;gap:8px;line-height:1.4;min-width:0;overflow:hidden;text-decoration:none;text-overflow:ellipsis;white-space:nowrap}.rm-sb__toggle{-moz-appearance:none;appearance:none;-webkit-appearance:none;background:none;border:none;border-radius:0;box-shadow:none;color:var(--rm-shell-text-muted);cursor:pointer;display:block;flex-shrink:0;height:20px;margin:0;padding:0;transition:color .15s;width:20px}.rm-sb__toggle:hover{color:var(--rm-shell-text)}.rm-sb__toggle svg{display:block;height:100%;width:100%}.rm-sb__nav{display:flex;flex:1;flex-direction:column;gap:16px;overflow-y:auto;padding:16px}.rm-sb--collapsed .rm-sb__nav{padding-left:8px;padding-right:8px}.rm-sb__group{display:flex;flex-direction:column;gap:4px}.rm-sb__label{align-items:center;-moz-appearance:none;appearance:none;-webkit-appearance:none;background:none;border:none;border-radius:0;box-shadow:none;color:var(--rm-shell-text-muted);display:flex;font-family:inherit;font-size:10px;font-weight:500;gap:4px;letter-spacing:.025em;line-height:1.6;margin:0;padding:0 2px;text-align:left;text-transform:uppercase;width:100%}button.rm-sb__label{cursor:pointer}button.rm-sb__label:hover{color:var(--rm-shell-text)}.rm-sb__label-text{flex:1;min-width:0}.rm-sb__chev{display:block;flex-shrink:0;height:12px;transition:transform .2s;width:12px}.rm-sb__label[aria-expanded=true] .rm-sb__chev{transform:rotate(90deg)}.rm-sb__rule{background:var(--rm-shell-border);height:1px;margin:4px}.rm-mi{align-items:center;-moz-appearance:none;appearance:none;-webkit-appearance:none;background:none;border:none;border-radius:4px;box-shadow:none;color:var(--rm-shell-text);cursor:pointer;display:flex;font-family:inherit;gap:8px;height:26px;margin:0;padding:2px;text-align:left;text-decoration:none;transition:background-color .15s;width:100%}.rm-mi:hover{background:color-mix(in srgb,var(--rm-shell-subtle) 50%,transparent)}.rm-mi.rm-mi--active{background:var(--rm-shell-subtle)}.rm-mi.rm-mi--current{background:color-mix(in srgb,var(--rm-shell-accent) 5%,transparent)}.rm-mi.rm-mi--current .rm-mi__icon{background:var(--rm-shell-accent);color:#fff}.rm-mi.rm-mi--current .rm-mi__icon svg{stroke:#fff}.rm-mi__icon{align-items:center;background:var(--rm-shell-subtle);border-radius:4px;color:var(--rm-shell-text-dark);display:flex;flex-shrink:0;height:22px;justify-content:center;line-height:1;width:22px}.rm-mi__icon svg{display:block;height:14px;width:14px}.rm-mi__icon i{font-size:14px;line-height:1}.rm-mi__label{color:var(--rm-shell-text);flex:1;font-size:14px;line-height:1.625;min-width:0;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.rm-mi__badge{background:var(--rm-shell-subtle);border-radius:4px;color:var(--rm-shell-text-muted);flex-shrink:0;font-size:9px;font-weight:700;letter-spacing:.025em;padding:2px 4px;text-transform:uppercase}.rm-sb--collapsed .rm-mi{justify-content:center}.rm-sb--collapsed .rm-mi>:not(.rm-mi__icon),.rm-sb--collapsed .rm-sb__sub{display:none}.rm-sb__sub{display:flex;flex-direction:column;gap:2px;padding:2px 0 2px 28px}.rm-sb__sub-item{border-radius:4px;color:var(--rm-shell-text);display:block;font-size:14px;line-height:1.625;overflow:hidden;padding:2px 4px;text-decoration:none;text-overflow:ellipsis;white-space:nowrap}.rm-sb__sub-item:hover{background:color-mix(in srgb,var(--rm-shell-subtle) 50%,transparent)}.rm-rail__item{align-items:center;-moz-appearance:none;appearance:none;-webkit-appearance:none;background:none;border:none;border-radius:0;box-shadow:none;cursor:pointer;display:flex;flex-direction:column;font-family:inherit;gap:4px;margin:0;padding:12px 0 8px;text-decoration:none;width:100%}.rm-rail__avatar{align-items:center;border:2px solid var(--rm-shell-surface);border-radius:9999px;color:#fff;display:flex;font-size:14px;height:32px;justify-content:center;transition:opacity .15s;width:32px}.rm-rail__item:hover .rm-rail__avatar{opacity:.8}.rm-rail__tile{align-items:center;background:var(--rm-shell-subtle);border-radius:8px;color:var(--rm-shell-text-dark);display:flex;font-size:16px;height:32px;justify-content:center;transition:background-color .15s,color .15s;width:32px}.rm-rail__item:hover .rm-rail__tile{background:var(--rm-shell-border)}.rm-rail__item.rm-rail__item--active .rm-rail__tile{background:var(--rm-shell-accent);color:#fff}.rm-rail__caption{color:var(--rm-shell-text-muted);font-size:10px;line-height:1;max-width:100%;overflow:hidden;padding:0 2px;text-overflow:ellipsis;transition:color .15s;white-space:nowrap}.rm-rail__item--active .rm-rail__caption,.rm-rail__item:hover .rm-rail__caption{color:var(--rm-shell-text)}.rm-rail__bottom{display:flex;justify-content:center;margin-top:auto;padding-bottom:16px}.rm-lang{background:var(--rm-shell-subtle);border:1px solid var(--rm-shell-accent);border-radius:9999px;display:grid;gap:2px;grid-template-rows:1fr 1fr;padding:3px;position:relative}.rm-lang__thumb{background:var(--rm-shell-surface);border-radius:9999px;box-shadow:0 1px 4px rgba(30,41,59,.16);height:32px;left:3px;position:absolute;top:3px;transition:transform .26s cubic-bezier(.34,1.56,.64,1);width:32px}.rm-lang--second .rm-lang__thumb{transform:translateY(34px)}.rm-lang__option{align-items:center;-moz-appearance:none;appearance:none;-webkit-appearance:none;background:none;border:none;border-radius:9999px;box-shadow:none;cursor:pointer;display:flex;filter:grayscale(1);font-size:17px;height:32px;justify-content:center;line-height:1;margin:0;opacity:.5;padding:0;position:relative;transition:filter .18s ease,opacity .18s ease,transform .18s ease;width:32px}.rm-lang__option:hover{filter:grayscale(0);opacity:.85}.rm-lang__option.rm-lang__option--active{filter:grayscale(0);opacity:1}.rm-lang__option:focus-visible{outline:2px solid var(--rm-shell-accent);outline-offset:2px}@media (prefers-reduced-motion:reduce){.rm-lang__option,.rm-lang__thumb{transition:none}}.rm-hd{background:var(--rm-shell-surface);border-bottom:1px solid var(--rm-shell-border);display:flex;flex-direction:column;flex-shrink:0}.rm-hd__row{gap:16px;height:var(--rm-bar-h);padding:0 16px}.rm-hd__crumbs,.rm-hd__row{align-items:center;display:flex}.rm-hd__crumbs{flex:1;font-size:14px;gap:4px;min-width:0}.rm-hd__crumb{align-items:center;color:var(--rm-shell-text-muted);display:inline-flex;gap:6px;text-decoration:none;transition:color .15s;white-space:nowrap}a.rm-hd__crumb:hover{color:var(--rm-shell-text)}.rm-hd__sep{color:var(--rm-shell-text-muted)}.rm-hd__picker{display:inline-flex;min-width:0;position:relative}.rm-hd__crumb--picker{-moz-appearance:none;appearance:none;-webkit-appearance:none;background:none;border:none;border-radius:4px;box-shadow:none;cursor:pointer;font:inherit;font-size:14px;margin:0;padding:2px 4px;transition:background-color .15s,color .15s}.rm-hd__crumb--picker:hover{background:var(--rm-shell-subtle)}.rm-hd__caret{display:block;flex-shrink:0;height:12px;opacity:.7;transition:transform .15s;width:12px}.rm-hd__caret--open{transform:rotate(180deg)}.rm-hd__menu{background:var(--rm-shell-surface);border:1px solid var(--rm-shell-border);border-radius:8px;box-shadow:0 8px 24px rgba(30,41,59,.12);left:0;max-height:60vh;max-width:320px;min-width:200px;overflow-y:auto;padding:4px;position:absolute;top:calc(100% + 4px);z-index:300}.rm-hd__menu-item{align-items:center;border-radius:4px;color:var(--rm-shell-text);display:flex;font-size:14px;gap:8px;line-height:1.5;overflow:hidden;padding:4px 6px;text-decoration:none;text-overflow:ellipsis;white-space:nowrap}.rm-hd__menu-item:hover{background:var(--rm-shell-subtle)}.rm-hd__menu-item--active{background:color-mix(in srgb,var(--rm-shell-accent) 5%,transparent);font-weight:600}.rm-hd__menu-icon{align-items:center;background:var(--rm-shell-subtle);border-radius:4px;color:var(--rm-shell-text-dark);display:flex;flex-shrink:0;height:22px;justify-content:center;line-height:1;width:22px}.rm-hd__menu-icon i{font-size:14px;line-height:1}.rm-hd__menu-item--active .rm-hd__menu-icon{background:var(--rm-shell-accent);color:#fff}.rm-hd__crumb--last{color:var(--rm-shell-text);font-weight:500;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.rm-hd__search{align-items:center;background:var(--rm-shell-surface);border:1px solid var(--rm-shell-border);border-radius:9999px;display:flex;flex-shrink:0;gap:4px;padding:4px 12px;width:300px}.rm-hd__search input{background:transparent;border:none;color:var(--rm-shell-text);flex:1;font-family:inherit;font-size:14px;line-height:20px;min-width:0;outline:none;padding:0}.rm-hd__search input::-moz-placeholder{color:var(--rm-shell-text-muted)}.rm-hd__search input::placeholder{color:var(--rm-shell-text-muted)}.rm-hd__search i,.rm-hd__search svg{color:var(--rm-shell-text-muted);display:block;flex-shrink:0;font-size:14px;height:14px;line-height:20px;width:14px}.rm-hd__tabs{display:flex;gap:16px;padding:0 16px}.rm-hd__tab{align-items:flex-start;-moz-appearance:none;appearance:none;-webkit-appearance:none;background:none;border:none;border-bottom:2px solid transparent;border-radius:0;box-shadow:none;color:var(--rm-shell-text-dark);cursor:pointer;display:flex;flex-direction:column;font-family:inherit;font-size:14px;font-weight:700;line-height:1.6;margin:0;padding:4px 4px 8px;white-space:nowrap}.rm-hd__tab--active{border-bottom-color:var(--rm-shell-accent);color:var(--rm-shell-text)}@media (max-width:767px){.rm-sb--left{inset:0 auto 0 0;position:absolute;transform:translateX(-100%);transition:transform .2s;z-index:40}.rm-sb--left.rm-sb--open{transform:translateX(0)}.rm-sb--right{display:none}.rm-hd__search{flex:1;width:auto}}.rm-panel{background:var(--rm-shell-surface);border-left:1px solid var(--rm-shell-border);bottom:0;box-shadow:-8px 0 24px rgba(30,41,59,.08);display:flex;flex-direction:column;position:absolute;right:0;top:0;width:var(--rm-panel-w,360px);z-index:200}.rm-sb--right{position:relative;z-index:201}.rm-panel-enter-active,.rm-panel-leave-active,.rm-sb--right{transition:transform .22s cubic-bezier(.4,0,.2,1)}.rm-panel-enter-from,.rm-panel-leave-to{transform:translateX(100%)}@media (prefers-reduced-motion:reduce){.rm-panel-enter-active,.rm-panel-leave-active,.rm-sb--right{transition:none}}.rm-panel__header{align-items:center;border-bottom:1px solid var(--rm-shell-border);display:flex;flex-shrink:0;gap:8px;height:var(--rm-bar-h);padding:0 16px}.rm-panel__title{color:var(--rm-shell-text);flex:1;font-size:14px;font-weight:600;min-width:0;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.rm-panel__close{-moz-appearance:none;appearance:none;-webkit-appearance:none;background:none;border:none;border-radius:0;box-shadow:none;color:var(--rm-shell-text-muted);cursor:pointer;display:block;flex-shrink:0;height:20px;margin:0;padding:0;transition:color .15s;width:20px}.rm-panel__close:hover{color:var(--rm-shell-text)}.rm-panel__close svg{display:block;height:100%;width:100%}.rm-panel__body{flex:1;min-height:0;overflow-y:auto;padding:16px}@media (max-width:767px){.rm-panel{border-left:none;left:0;width:auto}}
|
|
1
|
+
:root{--rm-shell-bg:#f9f9fa;--rm-shell-surface:#fff;--rm-shell-border:#dbdef0;--rm-shell-subtle:#f5f5f9;--rm-shell-text:#1e293b;--rm-shell-text-dark:#475569;--rm-shell-text-muted:#878ca6;--rm-shell-accent:#2017ad;--rm-shell-inset:8px;--rm-shell-radius:12px;--rm-bar-h:56px;--rm-nav-w:240px;--rm-nav-collapsed-w:64px;--rm-rail-w:56px;--rm-dots-image:url("data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAACgAAAAoCAYAAACM/rhtAAAAcUlEQVR42u3TwQmAMAxAUdfQfUoSZ3OBTNMFHEqLVBEtCB6M8B8EevwktOsAAACAl0SkNzNXtaw6zut7SikNYeJq2Hksh4gs27rG7ZH+eWA7bttigMC78x4TIdBbceX8fJKnkSL1s5RY8zBxAAAA+LUF0ula10BxVDoAAAAASUVORK5CYII=");--rm-dots-size:12px;--rm-dots-opacity:0.1}body.night{--rm-shell-bg:var(--bg-app);--rm-shell-surface:var(--bg-surface,#1a1a24);--rm-shell-border:var(--border-default);--rm-shell-subtle:var(--bg-subtle,#22222e);--rm-shell-text:var(--text-primary);--rm-shell-text-dark:var(--text-secondary);--rm-shell-text-muted:var(--text-muted);--rm-shell-accent:var(--color-primary);--rm-dots-opacity:0.06}.rm-shell{background:var(--rm-shell-bg);color:var(--rm-shell-text);font-family:var(--font-sans,"Figtree",sans-serif);inset:0;overflow:hidden;position:fixed}.rm-shell__dots{background-image:var(--rm-dots-image);background-repeat:repeat;background-size:var(--rm-dots-size) var(--rm-dots-size);inset:0;opacity:var(--rm-dots-opacity);pointer-events:none;position:absolute}.rm-shell__frame{border:1px solid var(--rm-shell-border);border-radius:var(--rm-shell-radius);display:flex;inset:var(--rm-shell-inset);overflow:hidden;position:absolute}.rm-shell__body{display:flex;flex:1;flex-direction:column;min-width:0}.rm-shell__main{flex:1;min-width:0;overflow-y:auto}.rm-sb{background:var(--rm-shell-surface);display:flex;flex-direction:column;flex-shrink:0;height:100%}.rm-sb--left{border-right:1px solid var(--rm-shell-border);position:relative;transition:width .2s;width:var(--rm-nav-w);z-index:200}.rm-sb--left.rm-sb--collapsed{width:var(--rm-nav-collapsed-w)}.rm-sb--right{border-left:1px solid var(--rm-shell-border);width:var(--rm-rail-w)}.rm-sb__header{align-items:center;border-bottom:1px solid var(--rm-shell-border);display:flex;flex-shrink:0;gap:8px;height:var(--rm-bar-h);padding:0 16px}.rm-sb--collapsed .rm-sb__header{justify-content:center;padding:0}.rm-sb__logo{align-items:center;color:var(--rm-shell-text);display:flex;flex:1;font-size:20px;font-weight:700;gap:8px;line-height:1.4;min-width:0;overflow:hidden;text-decoration:none;text-overflow:ellipsis;white-space:nowrap}.rm-sb__toggle{-moz-appearance:none;appearance:none;-webkit-appearance:none;background:none;border:none;border-radius:0;box-shadow:none;color:var(--rm-shell-text-muted);cursor:pointer;display:block;flex-shrink:0;height:20px;margin:0;padding:0;transition:color .15s;width:20px}.rm-sb__toggle:hover{color:var(--rm-shell-text)}.rm-sb__toggle svg{display:block;height:100%;width:100%}.rm-sb__nav{display:flex;flex:1;flex-direction:column;gap:16px;overflow-y:auto;padding:16px}.rm-sb--collapsed .rm-sb__nav{padding-left:8px;padding-right:8px}.rm-sb__group{display:flex;flex-direction:column;gap:4px}.rm-sb__label{align-items:center;-moz-appearance:none;appearance:none;-webkit-appearance:none;background:none;border:none;border-radius:0;box-shadow:none;color:var(--rm-shell-text-muted);display:flex;font-family:inherit;font-size:10px;font-weight:500;gap:4px;letter-spacing:.025em;line-height:1.6;margin:0;padding:0 2px;text-align:left;text-transform:uppercase;width:100%}button.rm-sb__label{cursor:pointer}button.rm-sb__label:hover{color:var(--rm-shell-text)}.rm-sb__label-text{flex:1;min-width:0}.rm-sb__chev{display:block;flex-shrink:0;height:12px;transition:transform .2s;width:12px}.rm-sb__label[aria-expanded=true] .rm-sb__chev{transform:rotate(90deg)}.rm-sb__rule{background:var(--rm-shell-border);height:1px;margin:4px}.rm-mi{align-items:center;-moz-appearance:none;appearance:none;-webkit-appearance:none;background:none;border:none;border-radius:4px;box-shadow:none;color:var(--rm-shell-text);cursor:pointer;display:flex;font-family:inherit;gap:8px;height:26px;margin:0;padding:2px;text-align:left;text-decoration:none;transition:background-color .15s;width:100%}.rm-mi:hover{background:color-mix(in srgb,var(--rm-shell-subtle) 50%,transparent)}.rm-mi.rm-mi--active{background:var(--rm-shell-subtle)}.rm-mi.rm-mi--current{background:color-mix(in srgb,var(--rm-shell-accent) 5%,transparent)}.rm-mi.rm-mi--current .rm-mi__icon{background:var(--rm-shell-accent);color:#fff}.rm-mi.rm-mi--current .rm-mi__icon svg{stroke:#fff}.rm-mi__icon{align-items:center;background:var(--rm-shell-subtle);border-radius:4px;color:var(--rm-shell-text-dark);display:flex;flex-shrink:0;height:22px;justify-content:center;line-height:1;width:22px}.rm-mi__icon svg{display:block;height:14px;width:14px}.rm-mi__icon i{font-size:14px;line-height:1}.rm-mi__label{color:var(--rm-shell-text);flex:1;font-size:14px;line-height:1.625;min-width:0;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.rm-mi__badge{background:var(--rm-shell-subtle);border-radius:4px;color:var(--rm-shell-text-muted);flex-shrink:0;font-size:9px;font-weight:700;letter-spacing:.025em;padding:2px 4px;text-transform:uppercase}.rm-sb--collapsed .rm-mi{justify-content:center}.rm-sb--collapsed .rm-mi>:not(.rm-mi__icon),.rm-sb--collapsed .rm-sb__sub{display:none}.rm-sb__sub{display:flex;flex-direction:column;gap:2px;padding:2px 0 2px 28px}.rm-sb__sub-item{border-radius:4px;color:var(--rm-shell-text);display:block;font-size:14px;line-height:1.625;overflow:hidden;padding:2px 4px;text-decoration:none;text-overflow:ellipsis;white-space:nowrap}.rm-sb__sub-item:hover{background:color-mix(in srgb,var(--rm-shell-subtle) 50%,transparent)}.rm-rail__item{align-items:center;-moz-appearance:none;appearance:none;-webkit-appearance:none;background:none;border:none;border-radius:0;box-shadow:none;cursor:pointer;display:flex;flex-direction:column;font-family:inherit;gap:4px;margin:0;padding:12px 0 8px;text-decoration:none;width:100%}.rm-rail__avatar{align-items:center;border:2px solid var(--rm-shell-surface);border-radius:9999px;color:#fff;display:flex;font-size:14px;height:32px;justify-content:center;transition:opacity .15s;width:32px}.rm-rail__item:hover .rm-rail__avatar{opacity:.8}.rm-rail__tile{align-items:center;background:var(--rm-shell-subtle);border-radius:8px;color:var(--rm-shell-text-dark);display:flex;font-size:16px;height:32px;justify-content:center;transition:background-color .15s,color .15s;width:32px}.rm-rail__item:hover .rm-rail__tile{background:var(--rm-shell-border)}.rm-rail__item.rm-rail__item--active .rm-rail__tile{background:var(--rm-shell-accent);color:#fff}.rm-rail__caption{color:var(--rm-shell-text-muted);font-size:10px;line-height:1;max-width:100%;overflow:hidden;padding:0 2px;text-overflow:ellipsis;transition:color .15s;white-space:nowrap}.rm-rail__item--active .rm-rail__caption,.rm-rail__item:hover .rm-rail__caption{color:var(--rm-shell-text)}.rm-rail__bottom{display:flex;justify-content:center;margin-top:auto;padding-bottom:16px}.rm-lang{background:var(--rm-shell-subtle);border:1px solid var(--rm-shell-accent);border-radius:9999px;display:grid;gap:2px;grid-template-rows:1fr 1fr;padding:3px;position:relative}.rm-lang__thumb{background:var(--rm-shell-surface);border-radius:9999px;box-shadow:0 1px 4px rgba(30,41,59,.16);height:32px;left:3px;position:absolute;top:3px;transition:transform .26s cubic-bezier(.34,1.56,.64,1);width:32px}.rm-lang--second .rm-lang__thumb{transform:translateY(34px)}.rm-lang__option{align-items:center;-moz-appearance:none;appearance:none;-webkit-appearance:none;background:none;border:none;border-radius:9999px;box-shadow:none;cursor:pointer;display:flex;filter:grayscale(1);font-size:17px;height:32px;justify-content:center;line-height:1;margin:0;opacity:.5;padding:0;position:relative;transition:filter .18s ease,opacity .18s ease,transform .18s ease;width:32px}.rm-lang__option:hover{filter:grayscale(0);opacity:.85}.rm-lang__option.rm-lang__option--active{filter:grayscale(0);opacity:1}.rm-lang__option:focus-visible{outline:2px solid var(--rm-shell-accent);outline-offset:2px}@media (prefers-reduced-motion:reduce){.rm-lang__option,.rm-lang__thumb{transition:none}}.rm-hd{background:var(--rm-shell-surface);border-bottom:1px solid var(--rm-shell-border);display:flex;flex-direction:column;flex-shrink:0}.rm-hd__row{gap:16px;height:var(--rm-bar-h);padding:0 16px}.rm-hd__crumbs,.rm-hd__row{align-items:center;display:flex}.rm-hd__crumbs{flex:1;font-size:14px;gap:4px;min-width:0}.rm-hd__crumb{align-items:center;color:var(--rm-shell-text-muted);display:inline-flex;gap:6px;text-decoration:none;transition:color .15s;white-space:nowrap}a.rm-hd__crumb:hover{color:var(--rm-shell-text)}.rm-hd__sep{color:var(--rm-shell-text-muted)}.rm-hd__picker{display:inline-flex;min-width:0;position:relative}.rm-hd__crumb--picker{-moz-appearance:none;appearance:none;-webkit-appearance:none;background:none;border:none;border-radius:4px;box-shadow:none;cursor:pointer;font:inherit;font-size:14px;margin:0;padding:2px 4px;transition:background-color .15s,color .15s}.rm-hd__crumb--picker:hover{background:var(--rm-shell-subtle)}.rm-hd__caret{display:block;flex-shrink:0;height:12px;opacity:.7;transition:transform .15s;width:12px}.rm-hd__caret--open{transform:rotate(180deg)}.rm-hd__menu{background:var(--rm-shell-surface);border:1px solid var(--rm-shell-border);border-radius:8px;box-shadow:0 8px 24px rgba(30,41,59,.12);left:0;max-height:60vh;max-width:320px;min-width:200px;overflow-y:auto;padding:4px;position:absolute;top:calc(100% + 4px);z-index:300}.rm-hd__menu-item{align-items:center;border-radius:4px;color:var(--rm-shell-text);display:flex;font-size:14px;gap:8px;line-height:1.5;overflow:hidden;padding:4px 6px;text-decoration:none;text-overflow:ellipsis;white-space:nowrap}.rm-hd__menu-item:hover{background:var(--rm-shell-subtle)}.rm-hd__menu-group{color:var(--rm-shell-text-muted);display:block;font-size:10px;font-weight:500;letter-spacing:.025em;line-height:1.6;padding:8px 6px 2px;text-transform:uppercase}.rm-hd__menu-group:first-child{padding-top:2px}.rm-hd__menu-item--active{background:color-mix(in srgb,var(--rm-shell-accent) 5%,transparent);font-weight:600}.rm-hd__menu-icon{align-items:center;background:var(--rm-shell-subtle);border-radius:4px;color:var(--rm-shell-text-dark);display:flex;flex-shrink:0;height:22px;justify-content:center;line-height:1;width:22px}.rm-hd__menu-icon i{font-size:14px;line-height:1}.rm-hd__menu-item--active .rm-hd__menu-icon{background:var(--rm-shell-accent);color:#fff}.rm-hd__crumb--last{color:var(--rm-shell-text);font-weight:500;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.rm-hd__search{align-items:center;background:var(--rm-shell-surface);border:1px solid var(--rm-shell-border);border-radius:9999px;display:flex;flex-shrink:0;gap:4px;padding:4px 12px;width:300px}.rm-hd__search input{background:transparent;border:none;color:var(--rm-shell-text);flex:1;font-family:inherit;font-size:14px;line-height:20px;min-width:0;outline:none;padding:0}.rm-hd__search input::-moz-placeholder{color:var(--rm-shell-text-muted)}.rm-hd__search input::placeholder{color:var(--rm-shell-text-muted)}.rm-hd__search i,.rm-hd__search svg{color:var(--rm-shell-text-muted);display:block;flex-shrink:0;font-size:14px;height:14px;line-height:20px;width:14px}.rm-hd__tabs{display:flex;gap:16px;padding:0 16px}.rm-hd__tab{align-items:flex-start;-moz-appearance:none;appearance:none;-webkit-appearance:none;background:none;border:none;border-bottom:2px solid transparent;border-radius:0;box-shadow:none;color:var(--rm-shell-text-dark);cursor:pointer;display:flex;flex-direction:column;font-family:inherit;font-size:14px;font-weight:700;line-height:1.6;margin:0;padding:4px 4px 8px;white-space:nowrap}.rm-hd__tab--active{border-bottom-color:var(--rm-shell-accent);color:var(--rm-shell-text)}@media (max-width:767px){.rm-sb--left{inset:0 auto 0 0;position:absolute;transform:translateX(-100%);transition:transform .2s;z-index:40}.rm-sb--left.rm-sb--open{transform:translateX(0)}.rm-sb--right{display:none}.rm-hd__search{flex:1;width:auto}}.rm-panel{background:var(--rm-shell-surface);border-left:1px solid var(--rm-shell-border);bottom:0;box-shadow:-8px 0 24px rgba(30,41,59,.08);display:flex;flex-direction:column;position:absolute;right:0;top:0;width:var(--rm-panel-w,360px);z-index:200}.rm-sb--right{position:relative;z-index:201}.rm-panel-enter-active,.rm-panel-leave-active,.rm-sb--right{transition:transform .22s cubic-bezier(.4,0,.2,1)}.rm-panel-enter-from,.rm-panel-leave-to{transform:translateX(100%)}@media (prefers-reduced-motion:reduce){.rm-panel-enter-active,.rm-panel-leave-active,.rm-sb--right{transition:none}}.rm-panel__header{align-items:center;border-bottom:1px solid var(--rm-shell-border);display:flex;flex-shrink:0;gap:8px;height:var(--rm-bar-h);padding:0 16px}.rm-panel__title{color:var(--rm-shell-text);flex:1;font-size:14px;font-weight:600;min-width:0;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.rm-panel__close{-moz-appearance:none;appearance:none;-webkit-appearance:none;background:none;border:none;border-radius:0;box-shadow:none;color:var(--rm-shell-text-muted);cursor:pointer;display:block;flex-shrink:0;height:20px;margin:0;padding:0;transition:color .15s;width:20px}.rm-panel__close:hover{color:var(--rm-shell-text)}.rm-panel__close svg{display:block;height:100%;width:100%}.rm-panel__body{flex:1;min-height:0;overflow-y:auto;padding:16px}@media (max-width:767px){.rm-panel{border-left:none;left:0;width:auto}}
|
|
@@ -30,6 +30,13 @@ export interface RmCrumbMenuItem {
|
|
|
30
30
|
icon?: string
|
|
31
31
|
/** Entree correspondant a l'endroit ou on se trouve deja. */
|
|
32
32
|
active?: boolean
|
|
33
|
+
/**
|
|
34
|
+
* Categorie. Les entrees restent une liste a plat ; un intitule est pose
|
|
35
|
+
* chaque fois que la valeur change, ce qui rend les groupes du menu sans
|
|
36
|
+
* imposer a l'appelant de fabriquer un tableau de tableaux. A lui de livrer
|
|
37
|
+
* ses entrees deja triees par groupe.
|
|
38
|
+
*/
|
|
39
|
+
group?: string
|
|
33
40
|
}
|
|
34
41
|
|
|
35
42
|
export interface RmCrumb {
|
|
@@ -130,7 +137,12 @@ onBeforeUnmount(() => {
|
|
|
130
137
|
<!-- Les deux branches sont ecrites en dur : `<component :is="'NuxtLink'">`
|
|
131
138
|
ne resout rien, les composants de Nuxt sont auto-importes a la
|
|
132
139
|
compilation et non enregistres a l'execution. -->
|
|
133
|
-
<template v-for="item in crumb.menu" :key="item.to ?? item.href ?? item.label">
|
|
140
|
+
<template v-for="(item, j) in crumb.menu" :key="item.to ?? item.href ?? item.label">
|
|
141
|
+
<span
|
|
142
|
+
v-if="item.group && item.group !== crumb.menu[j - 1]?.group"
|
|
143
|
+
class="rm-hd__menu-group"
|
|
144
|
+
role="presentation"
|
|
145
|
+
>{{ item.group }}</span>
|
|
134
146
|
<a
|
|
135
147
|
v-if="item.href"
|
|
136
148
|
:href="item.href"
|
|
@@ -6,6 +6,7 @@
|
|
|
6
6
|
import { computed } from 'vue'
|
|
7
7
|
import { useChartTheme } from '../composables/useChartTheme'
|
|
8
8
|
import { rmLineOption, type RmSeriesInput, RM_CHART_HEIGHTS } from '../utils/chart'
|
|
9
|
+
import { rmCompact, rmNumber } from '../utils/format'
|
|
9
10
|
|
|
10
11
|
const props = withDefaults(defineProps<{
|
|
11
12
|
categories: (string | number)[]
|
|
@@ -20,6 +21,29 @@ const props = withDefaults(defineProps<{
|
|
|
20
21
|
* `axis: 1` : deux unites sur un graphe sans libelle d'axe se lisent mal.
|
|
21
22
|
*/
|
|
22
23
|
axisLabels?: [string, string]
|
|
24
|
+
/**
|
|
25
|
+
* Etiquette chaque point de sa valeur, en pastille de la couleur de la
|
|
26
|
+
* serie. A reserver aux series courtes, sinon les pastilles se chevauchent.
|
|
27
|
+
*/
|
|
28
|
+
valueLabels?: boolean
|
|
29
|
+
/**
|
|
30
|
+
* Masque la graduation de l'axe des ordonnees, lignes de fond gardees. Ne
|
|
31
|
+
* s'utilise qu'avec `valueLabels`, sinon le graphe perd tout chiffre.
|
|
32
|
+
*/
|
|
33
|
+
hideValueAxis?: boolean
|
|
34
|
+
/** Position de la legende. */
|
|
35
|
+
legendPosition?: 'top' | 'bottom'
|
|
36
|
+
/**
|
|
37
|
+
* Ancre l'axe a zero quand toutes les valeurs sont positives, pour ne pas
|
|
38
|
+
* exagerer visuellement de faibles variations.
|
|
39
|
+
*/
|
|
40
|
+
startAtZero?: boolean
|
|
41
|
+
/**
|
|
42
|
+
* Format des valeurs, dans les etiquettes comme dans l'infobulle.
|
|
43
|
+
* `compact` abrege ("18,8 M") quand la place manque ; `plain` garde le
|
|
44
|
+
* nombre entier avec ses separateurs de milliers.
|
|
45
|
+
*/
|
|
46
|
+
numberFormat?: 'compact' | 'plain'
|
|
23
47
|
height?: keyof typeof RM_CHART_HEIGHTS | number
|
|
24
48
|
description?: string
|
|
25
49
|
}>(), {
|
|
@@ -27,12 +51,23 @@ const props = withDefaults(defineProps<{
|
|
|
27
51
|
step: false,
|
|
28
52
|
smooth: true,
|
|
29
53
|
axisLabels: undefined,
|
|
54
|
+
valueLabels: false,
|
|
55
|
+
hideValueAxis: false,
|
|
56
|
+
legendPosition: 'top',
|
|
57
|
+
startAtZero: false,
|
|
58
|
+
numberFormat: undefined,
|
|
30
59
|
height: 'standard',
|
|
31
60
|
description: undefined,
|
|
32
61
|
})
|
|
33
62
|
|
|
34
63
|
const { theme, palette, decal } = useChartTheme()
|
|
35
64
|
|
|
65
|
+
const formatter = computed(() => {
|
|
66
|
+
if (props.numberFormat === 'compact') return rmCompact
|
|
67
|
+
if (props.numberFormat === 'plain') return rmNumber
|
|
68
|
+
return undefined
|
|
69
|
+
})
|
|
70
|
+
|
|
36
71
|
const option = computed(() =>
|
|
37
72
|
rmLineOption(props.categories, props.series, theme.value, palette.value.cat, {
|
|
38
73
|
area: props.area,
|
|
@@ -40,6 +75,11 @@ const option = computed(() =>
|
|
|
40
75
|
smooth: props.smooth,
|
|
41
76
|
decal: decal.value,
|
|
42
77
|
axisLabels: props.axisLabels,
|
|
78
|
+
valueLabels: props.valueLabels,
|
|
79
|
+
hideValueAxis: props.hideValueAxis,
|
|
80
|
+
legendPosition: props.legendPosition,
|
|
81
|
+
startAtZero: props.startAtZero,
|
|
82
|
+
valueFormatter: formatter.value,
|
|
43
83
|
}),
|
|
44
84
|
)
|
|
45
85
|
</script>
|
|
@@ -288,14 +288,67 @@ export declare function rmLineOption(categories: (string | number)[], series: Rm
|
|
|
288
288
|
decal?: boolean;
|
|
289
289
|
/** Libelles des deux axes, requis des qu'une serie porte `axis: 1`. */
|
|
290
290
|
axisLabels?: [string, string];
|
|
291
|
+
/**
|
|
292
|
+
* Etiquette la valeur de chaque point, en pastille de la couleur de sa
|
|
293
|
+
* serie. Reserve aux series courtes : au-dela d'une quinzaine de points
|
|
294
|
+
* les pastilles se chevauchent et deviennent illisibles.
|
|
295
|
+
*/
|
|
296
|
+
valueLabels?: boolean;
|
|
297
|
+
/**
|
|
298
|
+
* Masque la graduation de l'axe des ordonnees, lignes de fond gardees.
|
|
299
|
+
* A n'activer qu'avec `valueLabels` : sans graduation NI etiquette, le
|
|
300
|
+
* graphe ne porte plus aucun chiffre.
|
|
301
|
+
*/
|
|
302
|
+
hideValueAxis?: boolean;
|
|
303
|
+
/** Position de la legende. `bottom` degage le haut du graphe. */
|
|
304
|
+
legendPosition?: 'top' | 'bottom';
|
|
305
|
+
/**
|
|
306
|
+
* Ancre l'axe a zero quand toutes les valeurs sont positives. Sans ca
|
|
307
|
+
* ECharts cadre sur l'amplitude des donnees et exagere les variations :
|
|
308
|
+
* une serie qui oscille de 3 % occupe alors toute la hauteur.
|
|
309
|
+
* Ignore des qu'une valeur est negative, ou l'axe doit descendre plus bas.
|
|
310
|
+
*/
|
|
311
|
+
startAtZero?: boolean;
|
|
312
|
+
/** Formate les valeurs, dans les etiquettes comme dans l'infobulle. */
|
|
313
|
+
valueFormatter?: (value: number) => string;
|
|
291
314
|
}): {
|
|
315
|
+
tooltip: {
|
|
316
|
+
trigger: string;
|
|
317
|
+
backgroundColor: string;
|
|
318
|
+
textStyle: {
|
|
319
|
+
color: string;
|
|
320
|
+
fontFamily: string;
|
|
321
|
+
fontSize: number;
|
|
322
|
+
};
|
|
323
|
+
borderColor: string;
|
|
324
|
+
borderWidth: number;
|
|
325
|
+
} | {
|
|
326
|
+
valueFormatter: (value: unknown) => string;
|
|
327
|
+
trigger: string;
|
|
328
|
+
backgroundColor: string;
|
|
329
|
+
textStyle: {
|
|
330
|
+
color: string;
|
|
331
|
+
fontFamily: string;
|
|
332
|
+
fontSize: number;
|
|
333
|
+
};
|
|
334
|
+
borderColor: string;
|
|
335
|
+
borderWidth: number;
|
|
336
|
+
};
|
|
292
337
|
legend: {
|
|
293
|
-
top: number;
|
|
294
338
|
textStyle: {
|
|
295
339
|
color: string;
|
|
296
340
|
fontSize: number;
|
|
297
341
|
fontFamily: string;
|
|
298
342
|
};
|
|
343
|
+
bottom: number;
|
|
344
|
+
left: string;
|
|
345
|
+
} | {
|
|
346
|
+
textStyle: {
|
|
347
|
+
color: string;
|
|
348
|
+
fontSize: number;
|
|
349
|
+
fontFamily: string;
|
|
350
|
+
};
|
|
351
|
+
top: number;
|
|
299
352
|
} | undefined;
|
|
300
353
|
grid: {
|
|
301
354
|
left: number;
|
|
@@ -322,7 +375,8 @@ export declare function rmLineOption(categories: (string | number)[], series: Rm
|
|
|
322
375
|
type: string;
|
|
323
376
|
data: (string | number)[];
|
|
324
377
|
};
|
|
325
|
-
yAxis: {
|
|
378
|
+
yAxis: ({
|
|
379
|
+
min: number | undefined;
|
|
326
380
|
type: string;
|
|
327
381
|
name: string | undefined;
|
|
328
382
|
nameLocation: string;
|
|
@@ -334,21 +388,38 @@ export declare function rmLineOption(categories: (string | number)[], series: Rm
|
|
|
334
388
|
align: string;
|
|
335
389
|
};
|
|
336
390
|
axisLabel: {
|
|
391
|
+
show: boolean;
|
|
392
|
+
fontSize?: undefined;
|
|
393
|
+
color?: undefined;
|
|
394
|
+
fontFamily?: undefined;
|
|
395
|
+
} | {
|
|
337
396
|
fontSize: number;
|
|
338
397
|
color: string;
|
|
339
398
|
fontFamily: string;
|
|
399
|
+
show?: undefined;
|
|
340
400
|
};
|
|
341
401
|
axisLine: {
|
|
402
|
+
show: boolean;
|
|
403
|
+
lineStyle?: undefined;
|
|
404
|
+
} | {
|
|
342
405
|
lineStyle: {
|
|
343
406
|
color: string;
|
|
344
407
|
};
|
|
408
|
+
show?: undefined;
|
|
345
409
|
};
|
|
410
|
+
axisTick: {
|
|
411
|
+
show: boolean;
|
|
412
|
+
} | undefined;
|
|
346
413
|
splitLine: {
|
|
347
414
|
lineStyle: {
|
|
348
415
|
color: string;
|
|
349
416
|
};
|
|
350
417
|
};
|
|
351
|
-
} |
|
|
418
|
+
} | {
|
|
419
|
+
splitLine: {
|
|
420
|
+
show: boolean;
|
|
421
|
+
};
|
|
422
|
+
min: number | undefined;
|
|
352
423
|
type: string;
|
|
353
424
|
name: string | undefined;
|
|
354
425
|
nameLocation: string;
|
|
@@ -360,24 +431,30 @@ export declare function rmLineOption(categories: (string | number)[], series: Rm
|
|
|
360
431
|
align: string;
|
|
361
432
|
};
|
|
362
433
|
axisLabel: {
|
|
434
|
+
show: boolean;
|
|
435
|
+
fontSize?: undefined;
|
|
436
|
+
color?: undefined;
|
|
437
|
+
fontFamily?: undefined;
|
|
438
|
+
} | {
|
|
363
439
|
fontSize: number;
|
|
364
440
|
color: string;
|
|
365
441
|
fontFamily: string;
|
|
442
|
+
show?: undefined;
|
|
366
443
|
};
|
|
367
444
|
axisLine: {
|
|
445
|
+
show: boolean;
|
|
446
|
+
lineStyle?: undefined;
|
|
447
|
+
} | {
|
|
368
448
|
lineStyle: {
|
|
369
449
|
color: string;
|
|
370
450
|
};
|
|
451
|
+
show?: undefined;
|
|
371
452
|
};
|
|
372
|
-
|
|
373
|
-
lineStyle: {
|
|
374
|
-
color: string;
|
|
375
|
-
};
|
|
376
|
-
};
|
|
377
|
-
} | {
|
|
378
|
-
splitLine: {
|
|
453
|
+
axisTick: {
|
|
379
454
|
show: boolean;
|
|
380
|
-
};
|
|
455
|
+
} | undefined;
|
|
456
|
+
})[] | {
|
|
457
|
+
min: number | undefined;
|
|
381
458
|
type: string;
|
|
382
459
|
name: string | undefined;
|
|
383
460
|
nameLocation: string;
|
|
@@ -389,16 +466,34 @@ export declare function rmLineOption(categories: (string | number)[], series: Rm
|
|
|
389
466
|
align: string;
|
|
390
467
|
};
|
|
391
468
|
axisLabel: {
|
|
469
|
+
show: boolean;
|
|
470
|
+
fontSize?: undefined;
|
|
471
|
+
color?: undefined;
|
|
472
|
+
fontFamily?: undefined;
|
|
473
|
+
} | {
|
|
392
474
|
fontSize: number;
|
|
393
475
|
color: string;
|
|
394
476
|
fontFamily: string;
|
|
477
|
+
show?: undefined;
|
|
395
478
|
};
|
|
396
479
|
axisLine: {
|
|
480
|
+
show: boolean;
|
|
481
|
+
lineStyle?: undefined;
|
|
482
|
+
} | {
|
|
483
|
+
lineStyle: {
|
|
484
|
+
color: string;
|
|
485
|
+
};
|
|
486
|
+
show?: undefined;
|
|
487
|
+
};
|
|
488
|
+
axisTick: {
|
|
489
|
+
show: boolean;
|
|
490
|
+
} | undefined;
|
|
491
|
+
splitLine: {
|
|
397
492
|
lineStyle: {
|
|
398
493
|
color: string;
|
|
399
494
|
};
|
|
400
495
|
};
|
|
401
|
-
}
|
|
496
|
+
};
|
|
402
497
|
series: {
|
|
403
498
|
type: string;
|
|
404
499
|
name: string | undefined;
|
|
@@ -408,6 +503,20 @@ export declare function rmLineOption(categories: (string | number)[], series: Rm
|
|
|
408
503
|
step: string | undefined;
|
|
409
504
|
symbol: string;
|
|
410
505
|
symbolSize: number;
|
|
506
|
+
label: {
|
|
507
|
+
show: boolean;
|
|
508
|
+
position: string;
|
|
509
|
+
distance: number;
|
|
510
|
+
fontSize: number;
|
|
511
|
+
fontFamily: string;
|
|
512
|
+
color: string;
|
|
513
|
+
backgroundColor: string;
|
|
514
|
+
padding: number[];
|
|
515
|
+
borderRadius: number;
|
|
516
|
+
formatter: (p: {
|
|
517
|
+
value: number | null;
|
|
518
|
+
}) => string;
|
|
519
|
+
} | undefined;
|
|
411
520
|
lineStyle: {
|
|
412
521
|
color: string;
|
|
413
522
|
width: number;
|
|
@@ -440,17 +549,6 @@ export declare function rmLineOption(categories: (string | number)[], series: Rm
|
|
|
440
549
|
textStyle: {
|
|
441
550
|
fontFamily: string;
|
|
442
551
|
};
|
|
443
|
-
tooltip: {
|
|
444
|
-
trigger: string;
|
|
445
|
-
backgroundColor: string;
|
|
446
|
-
textStyle: {
|
|
447
|
-
color: string;
|
|
448
|
-
fontFamily: string;
|
|
449
|
-
fontSize: number;
|
|
450
|
-
};
|
|
451
|
-
borderColor: string;
|
|
452
|
-
borderWidth: number;
|
|
453
|
-
};
|
|
454
552
|
};
|
|
455
553
|
/** Donut. Au-dela de 6 parts, regrouper le reste en "Autres". */
|
|
456
554
|
export declare function rmDonutOption(data: {
|
|
@@ -90,14 +90,15 @@ export function rmBaseOption(theme, decal = false) {
|
|
|
90
90
|
}
|
|
91
91
|
};
|
|
92
92
|
}
|
|
93
|
-
const valueAxis = (theme, label) => ({
|
|
93
|
+
const valueAxis = (theme, label, hidden = false) => ({
|
|
94
94
|
type: "value",
|
|
95
|
-
name: label,
|
|
95
|
+
name: hidden ? void 0 : label,
|
|
96
96
|
nameLocation: "end",
|
|
97
97
|
nameGap: 12,
|
|
98
98
|
nameTextStyle: { fontSize: 10, color: theme.dimmedColor, fontFamily: FONT, align: "left" },
|
|
99
|
-
axisLabel: { fontSize: 11, color: theme.mutedColor, fontFamily: FONT },
|
|
100
|
-
axisLine: { lineStyle: { color: theme.axisLine } },
|
|
99
|
+
axisLabel: hidden ? { show: false } : { fontSize: 11, color: theme.mutedColor, fontFamily: FONT },
|
|
100
|
+
axisLine: hidden ? { show: false } : { lineStyle: { color: theme.axisLine } },
|
|
101
|
+
axisTick: hidden ? { show: false } : void 0,
|
|
101
102
|
splitLine: { lineStyle: { color: theme.splitLine } }
|
|
102
103
|
});
|
|
103
104
|
const axisCommon = (theme) => ({
|
|
@@ -145,21 +146,54 @@ export function rmBarHorizontalOption(labels, values, theme, palette, decal = fa
|
|
|
145
146
|
};
|
|
146
147
|
}
|
|
147
148
|
export function rmLineOption(categories, series, theme, palette, options = {}) {
|
|
148
|
-
const {
|
|
149
|
+
const {
|
|
150
|
+
area = false,
|
|
151
|
+
step = false,
|
|
152
|
+
smooth = true,
|
|
153
|
+
decal = false,
|
|
154
|
+
axisLabels,
|
|
155
|
+
valueLabels = false,
|
|
156
|
+
hideValueAxis = false,
|
|
157
|
+
legendPosition = "top",
|
|
158
|
+
startAtZero = false,
|
|
159
|
+
valueFormatter
|
|
160
|
+
} = options;
|
|
149
161
|
const dual = series.some((s) => s.axis === 1);
|
|
162
|
+
const bottomLegend = legendPosition === "bottom";
|
|
163
|
+
const format = (value) => valueFormatter ? valueFormatter(value) : String(value);
|
|
164
|
+
const values = series.flatMap((s) => s.data).filter((v) => typeof v === "number");
|
|
165
|
+
const floorAtZero = startAtZero && values.length > 0 && Math.min(...values) >= 0;
|
|
166
|
+
const base = rmBaseOption(theme, decal);
|
|
150
167
|
return {
|
|
151
|
-
...
|
|
168
|
+
...base,
|
|
169
|
+
tooltip: valueFormatter ? {
|
|
170
|
+
...base.tooltip,
|
|
171
|
+
valueFormatter: (value) => typeof value === "number" ? format(value) : ""
|
|
172
|
+
} : base.tooltip,
|
|
152
173
|
// Legende obligatoire en double axe : sans elle, rien ne dit quelle courbe
|
|
153
174
|
// se lit sur quel axe.
|
|
154
|
-
legend: series.length > 1 || dual ? {
|
|
155
|
-
|
|
175
|
+
legend: series.length > 1 || dual ? {
|
|
176
|
+
...bottomLegend ? { bottom: 0, left: "center" } : { top: 0 },
|
|
177
|
+
textStyle: { color: theme.mutedColor, fontSize: 11, fontFamily: FONT }
|
|
178
|
+
} : void 0,
|
|
179
|
+
grid: {
|
|
180
|
+
// Sans graduation a gauche, la gouttiere de 48 px ne sert plus qu'a
|
|
181
|
+
// laisser depasser la premiere pastille de valeur.
|
|
182
|
+
left: hideValueAxis ? 24 : 48,
|
|
183
|
+
right: dual ? 56 : 16,
|
|
184
|
+
// Les pastilles du point le plus haut depassent la courbe : sans marge
|
|
185
|
+
// supplementaire en haut, ECharts les rogne.
|
|
186
|
+
top: dual ? 40 : valueLabels ? 32 : 24,
|
|
187
|
+
bottom: bottomLegend ? 56 : 36,
|
|
188
|
+
containLabel: true
|
|
189
|
+
},
|
|
156
190
|
xAxis: { type: "category", data: categories, ...axisCommon(theme), splitLine: { show: false }, boundaryGap: false },
|
|
157
191
|
yAxis: dual ? [
|
|
158
|
-
valueAxis(theme, axisLabels?.[0]),
|
|
192
|
+
{ ...valueAxis(theme, axisLabels?.[0], hideValueAxis), min: floorAtZero ? 0 : void 0 },
|
|
159
193
|
// Le second axe ne rejoue pas la grille : deux grilles superposees
|
|
160
194
|
// rendent le fond illisible.
|
|
161
|
-
{ ...valueAxis(theme, axisLabels?.[1]), splitLine: { show: false } }
|
|
162
|
-
] : valueAxis(theme, axisLabels?.[0]),
|
|
195
|
+
{ ...valueAxis(theme, axisLabels?.[1], hideValueAxis), splitLine: { show: false }, min: floorAtZero ? 0 : void 0 }
|
|
196
|
+
] : { ...valueAxis(theme, axisLabels?.[0], hideValueAxis), min: floorAtZero ? 0 : void 0 },
|
|
163
197
|
series: series.map((s, i) => {
|
|
164
198
|
const color = s.color ?? palette[i % palette.length];
|
|
165
199
|
return {
|
|
@@ -169,8 +203,22 @@ export function rmLineOption(categories, series, theme, palette, options = {}) {
|
|
|
169
203
|
data: s.data,
|
|
170
204
|
smooth: step ? false : smooth,
|
|
171
205
|
step: step ? "end" : void 0,
|
|
172
|
-
|
|
206
|
+
// La pastille de valeur marque deja le point : garder en plus le
|
|
207
|
+
// symbole empile deux marqueurs au meme endroit.
|
|
208
|
+
symbol: valueLabels ? "none" : "circle",
|
|
173
209
|
symbolSize: 5,
|
|
210
|
+
label: valueLabels ? {
|
|
211
|
+
show: true,
|
|
212
|
+
position: "top",
|
|
213
|
+
distance: 6,
|
|
214
|
+
fontSize: 11,
|
|
215
|
+
fontFamily: FONT,
|
|
216
|
+
color: "#FFFFFF",
|
|
217
|
+
backgroundColor: color,
|
|
218
|
+
padding: [3, 5],
|
|
219
|
+
borderRadius: 2,
|
|
220
|
+
formatter: (p) => p.value === null || p.value === void 0 ? "" : format(p.value)
|
|
221
|
+
} : void 0,
|
|
174
222
|
lineStyle: { color, width: 2.5 },
|
|
175
223
|
itemStyle: { color },
|
|
176
224
|
areaStyle: area ? {
|
|
@@ -25,3 +25,14 @@ export declare const rmBig: (n: number) => string;
|
|
|
25
25
|
export declare const rmPct: (n: number, digits?: number) => string;
|
|
26
26
|
/** "8,7" - decimale francaise sans unite (ratios : HR, OR, taux). */
|
|
27
27
|
export declare const rmDecimal: (n: number, digits?: number) => string;
|
|
28
|
+
/**
|
|
29
|
+
* "18,8 M" · "345 k" · "1,2 Md" - grands nombres abreges SANS unite, pour
|
|
30
|
+
* les etiquettes de graphe ou l'espace manque. Distinct de `rmBig`, qui colle
|
|
31
|
+
* un € et ne vaut donc que pour des montants ; ici on compte des boites, des
|
|
32
|
+
* patients, des actes.
|
|
33
|
+
*
|
|
34
|
+
* Passe par `Intl` en `fr-FR` et non par un suffixe anglais code a la main :
|
|
35
|
+
* la virgule decimale et l'espace insecable avant le suffixe sont la regle
|
|
36
|
+
* francaise, y compris sur un graphe.
|
|
37
|
+
*/
|
|
38
|
+
export declare const rmCompact: (n: number) => string;
|
|
@@ -5,3 +5,4 @@ export const rmPrice = (n) => n.toLocaleString("fr-FR") + " \u20AC";
|
|
|
5
5
|
export const rmBig = (n) => n >= 1e9 ? (n / 1e9).toFixed(1).replace(".", ",") + " Md\u20AC" : n >= 1e6 ? (n / 1e6).toFixed(0) + " M\u20AC" : n >= 1e3 ? (n / 1e3).toFixed(0) + " k" : String(n);
|
|
6
6
|
export const rmPct = (n, digits = 1) => (n > 0 ? "+" : "") + n.toFixed(digits).replace(".", ",") + " %";
|
|
7
7
|
export const rmDecimal = (n, digits = 1) => n.toFixed(digits).replace(".", ",");
|
|
8
|
+
export const rmCompact = (n) => new Intl.NumberFormat("fr-FR", { notation: "compact", maximumFractionDigits: 1 }).format(n);
|