@tekkare/romulus 0.1.73 → 0.1.75
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/ComplexSelect.vue +374 -0
- package/dist/runtime/components/DropdownSelect.vue +10 -2
- package/dist/runtime/components/FilterBar.vue +1 -1
- package/dist/runtime/components/MultipleSelect.vue +10 -2
- package/dist/runtime/components/ViewPill.vue +20 -5
- package/dist/runtime/utils/panels.d.ts +8 -0
- package/dist/runtime/utils/panels.js +10 -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__tip{background:var(--rm-shell-surface);border:1px solid var(--rm-shell-border);border-radius:6px;box-shadow:0 4px 12px rgba(30,41,59,.1);color:var(--rm-shell-text);font-size:12px;line-height:1.3;padding:5px 9px;pointer-events:none;position:fixed;transform:translateY(-50%);white-space:nowrap;z-index:60}.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__tile{position:relative}.rm-rail__badge{background:var(--rm-shell-accent);border-radius:9999px;color:#fff;font-size:10px;font-weight:700;height:16px;line-height:16px;min-width:16px;padding:0 4px;position:absolute;right:-4px;text-align:center;top:-4px}.rm-rail__item--active .rm-rail__badge{background:#fff;color:var(--rm-shell-accent)}.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:401}.rm-panel__veil{backdrop-filter:blur(3px);-webkit-backdrop-filter:blur(3px);background:var(--rm-panel-veil,rgba(100,116,139,.12));cursor:default;inset:0;position:absolute;z-index:400}.rm-panel-veil-enter-active,.rm-panel-veil-leave-active{transition:opacity .22s ease}.rm-panel-veil-enter-from,.rm-panel-veil-leave-to{opacity:0}@media (prefers-reduced-motion:reduce){.rm-panel-veil-enter-active,.rm-panel-veil-leave-active{transition:none}}.rm-sb--right{position:relative;z-index:402}.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__tip{background:var(--rm-shell-surface);border:1px solid var(--rm-shell-border);border-radius:6px;box-shadow:0 4px 12px rgba(30,41,59,.1);color:var(--rm-shell-text);font-size:12px;line-height:1.3;padding:5px 9px;pointer-events:none;position:fixed;transform:translateY(-50%);white-space:nowrap;z-index:60}.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__tile{position:relative}.rm-rail__badge{background:var(--rm-shell-accent);border-radius:9999px;color:#fff;font-size:10px;font-weight:700;height:16px;line-height:16px;min-width:16px;padding:0 4px;position:absolute;right:-4px;text-align:center;top:-4px}.rm-rail__item--active .rm-rail__badge{background:#fff;color:var(--rm-shell-accent)}.rm-rail__dot{animation:rm-rail-dot-pulse 2s ease-out infinite;background:var(--color-success,#16a34a);border:2px solid var(--rm-shell-surface);border-radius:9999px;height:10px;position:absolute;right:-2px;top:-2px;width:10px}@keyframes rm-rail-dot-pulse{0%{box-shadow:0 0 0 0 rgba(22,163,74,.55)}70%{box-shadow:0 0 0 6px rgba(22,163,74,0)}to{box-shadow:0 0 0 0 rgba(22,163,74,0)}}@media (prefers-reduced-motion:reduce){.rm-rail__dot{animation:none}}.rm-rail__item--active .rm-rail__dot{border-color:var(--rm-shell-accent)}.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:401}.rm-panel__veil{backdrop-filter:blur(3px);-webkit-backdrop-filter:blur(3px);background:var(--rm-panel-veil,rgba(100,116,139,.12));cursor:default;inset:0;position:absolute;z-index:400}.rm-panel-veil-enter-active,.rm-panel-veil-leave-active{transition:opacity .22s ease}.rm-panel-veil-enter-from,.rm-panel-veil-leave-to{opacity:0}@media (prefers-reduced-motion:reduce){.rm-panel-veil-enter-active,.rm-panel-veil-leave-active{transition:none}}.rm-sb--right{position:relative;z-index:402}.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}}
|
|
@@ -0,0 +1,374 @@
|
|
|
1
|
+
<!--
|
|
2
|
+
RmComplexSelect - champ de filtre a deux colonnes : ajouter d'un cote,
|
|
3
|
+
retirer de l'autre.
|
|
4
|
+
|
|
5
|
+
Reprend `arg-complex-select` d'Auriga : un intitule, un champ qui enumere la
|
|
6
|
+
selection, et un panneau large ou la colonne de gauche propose les valeurs
|
|
7
|
+
disponibles (avec selections rapides et recherche) pendant que celle de
|
|
8
|
+
droite tient la selection en cours.
|
|
9
|
+
|
|
10
|
+
Laquelle prendre : celle-ci quand le referentiel est trop long pour se
|
|
11
|
+
cocher d'un bloc (des milliers de marques, de molecules, de pays) ;
|
|
12
|
+
`RmMultipleSelect` pour une liste courte a cocher ; `RmFilterComplex` pour
|
|
13
|
+
la pastille equivalente dans une barre de filtres.
|
|
14
|
+
|
|
15
|
+
Trois choses changent par rapport a Auriga.
|
|
16
|
+
|
|
17
|
+
La selection est un `v-model`, plus le couple `already_selected` en entree
|
|
18
|
+
et `update:Selection` en sortie : les deux se repondaient en boucle des que
|
|
19
|
+
la page reposait la selection elle-meme.
|
|
20
|
+
|
|
21
|
+
Les lignes sont des boutons : la colonne se parcourt au clavier, alors
|
|
22
|
+
qu'Auriga posait des `div` avec un `@click` et un `@mouseover` pour changer
|
|
23
|
+
l'icone, invisible pour qui n'a pas de souris.
|
|
24
|
+
|
|
25
|
+
Le mode « appliquer / annuler » a ete laisse de cote : il etait deja mis en
|
|
26
|
+
commentaire dans Auriga, et aucune page ne l'appelait.
|
|
27
|
+
-->
|
|
28
|
+
<script setup lang="ts">
|
|
29
|
+
import { computed, nextTick, onMounted, onUnmounted, ref, watch } from 'vue'
|
|
30
|
+
import { rmPanelOpened, rmPanelRegister } from '../utils/panels'
|
|
31
|
+
|
|
32
|
+
export interface RmComplexSelectPreset {
|
|
33
|
+
label: string
|
|
34
|
+
values: string[]
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
const props = withDefaults(defineProps<{
|
|
38
|
+
/** Intitule pose au-dessus du champ. */
|
|
39
|
+
label: string
|
|
40
|
+
options: string[]
|
|
41
|
+
loading?: boolean
|
|
42
|
+
disabled?: boolean
|
|
43
|
+
/** Selections rapides. Vides, la section ne sort pas. */
|
|
44
|
+
presets?: RmComplexSelectPreset[] | null
|
|
45
|
+
/** Action « Tout » en tete de la colonne de gauche. */
|
|
46
|
+
showSelectAll?: boolean
|
|
47
|
+
/** L'action « Tout » annonce combien de valeurs elle ajouterait. */
|
|
48
|
+
selectAllCount?: boolean
|
|
49
|
+
/**
|
|
50
|
+
* La liste est tronquee par le serveur : le compte de l'action « Tout »
|
|
51
|
+
* s'annonce comme un maximum, sinon il se lit comme le total du
|
|
52
|
+
* referentiel.
|
|
53
|
+
*/
|
|
54
|
+
hasMore?: boolean
|
|
55
|
+
addPlaceholder?: string
|
|
56
|
+
removePlaceholder?: string
|
|
57
|
+
emptyLabel?: string
|
|
58
|
+
emptyContent?: string
|
|
59
|
+
/**
|
|
60
|
+
* Filtrage local de la colonne de gauche. A passer a `false` quand les
|
|
61
|
+
* options arrivent deja filtrees du serveur (cf. `RmDropdownSelect`).
|
|
62
|
+
*/
|
|
63
|
+
filterSearch?: boolean
|
|
64
|
+
/** Pastille du nombre de valeurs retenues, posee sur le champ. */
|
|
65
|
+
showAmount?: boolean
|
|
66
|
+
/** Pastille d'aide a cote de l'intitule, qui emet `openInfo`. */
|
|
67
|
+
labelInfo?: boolean
|
|
68
|
+
/** Nombre de lignes posees d'un coup dans la colonne de gauche. */
|
|
69
|
+
maxOptions?: number
|
|
70
|
+
lang?: 'fr' | 'en'
|
|
71
|
+
}>(), {
|
|
72
|
+
loading: false,
|
|
73
|
+
disabled: false,
|
|
74
|
+
presets: null,
|
|
75
|
+
showSelectAll: false,
|
|
76
|
+
selectAllCount: false,
|
|
77
|
+
hasMore: false,
|
|
78
|
+
addPlaceholder: undefined,
|
|
79
|
+
removePlaceholder: undefined,
|
|
80
|
+
emptyLabel: undefined,
|
|
81
|
+
emptyContent: undefined,
|
|
82
|
+
filterSearch: true,
|
|
83
|
+
showAmount: true,
|
|
84
|
+
labelInfo: false,
|
|
85
|
+
maxOptions: 500,
|
|
86
|
+
lang: 'fr',
|
|
87
|
+
})
|
|
88
|
+
|
|
89
|
+
const emit = defineEmits<{
|
|
90
|
+
/** Selection complete apres le changement. Double le `v-model`. */
|
|
91
|
+
change: [values: string[]]
|
|
92
|
+
/** Saisie de la colonne « ajouter », amortie a 500 ms. */
|
|
93
|
+
search: [value: string]
|
|
94
|
+
openInfo: []
|
|
95
|
+
}>()
|
|
96
|
+
|
|
97
|
+
const selected = defineModel<string[]>({ default: () => [] })
|
|
98
|
+
|
|
99
|
+
const WORDS = {
|
|
100
|
+
fr: {
|
|
101
|
+
empty: 'Aucune sélection',
|
|
102
|
+
quick: 'Sélection rapide',
|
|
103
|
+
add: 'Ajouter',
|
|
104
|
+
custom: 'Sélection personnalisée',
|
|
105
|
+
all: 'Tout',
|
|
106
|
+
current: 'Sélection en cours',
|
|
107
|
+
clear: 'Tout effacer',
|
|
108
|
+
searchAdd: 'Rechercher une valeur',
|
|
109
|
+
searchDel: 'Rechercher dans la sélection',
|
|
110
|
+
notFound: 'Aucun résultat',
|
|
111
|
+
loading: 'Chargement',
|
|
112
|
+
noSelection: 'Rien de retenu pour le moment',
|
|
113
|
+
},
|
|
114
|
+
en: {
|
|
115
|
+
empty: 'No selection',
|
|
116
|
+
quick: 'Quick selection',
|
|
117
|
+
add: 'Add',
|
|
118
|
+
custom: 'Custom selection',
|
|
119
|
+
all: 'All',
|
|
120
|
+
current: 'Current selection',
|
|
121
|
+
clear: 'Clear all',
|
|
122
|
+
searchAdd: 'Search a value',
|
|
123
|
+
searchDel: 'Search in the selection',
|
|
124
|
+
notFound: 'No result',
|
|
125
|
+
loading: 'Loading',
|
|
126
|
+
noSelection: 'Nothing selected yet',
|
|
127
|
+
},
|
|
128
|
+
} as const
|
|
129
|
+
|
|
130
|
+
const t = computed(() => WORDS[props.lang])
|
|
131
|
+
|
|
132
|
+
const isOpen = ref(false)
|
|
133
|
+
const addSearch = ref('')
|
|
134
|
+
const removeSearch = ref('')
|
|
135
|
+
const activePreset = ref<string>()
|
|
136
|
+
const rootRef = ref<HTMLElement>()
|
|
137
|
+
const addRef = ref<HTMLInputElement>()
|
|
138
|
+
|
|
139
|
+
/** La colonne de gauche ne propose que ce qui n'est pas deja retenu. */
|
|
140
|
+
const addOptions = computed(() => {
|
|
141
|
+
const needle = addSearch.value.trim().toLowerCase()
|
|
142
|
+
const parts = needle && props.filterSearch ? needle.split(' ').filter(Boolean) : []
|
|
143
|
+
return props.options
|
|
144
|
+
.filter(option => !selected.value.includes(option))
|
|
145
|
+
.filter(option => parts.every(part => option.toLowerCase().includes(part)))
|
|
146
|
+
.slice(0, props.maxOptions)
|
|
147
|
+
})
|
|
148
|
+
|
|
149
|
+
const removeOptions = computed(() => {
|
|
150
|
+
const needle = removeSearch.value.trim().toLowerCase()
|
|
151
|
+
if (!needle) return selected.value
|
|
152
|
+
return selected.value.filter(option => option.toLowerCase().includes(needle))
|
|
153
|
+
})
|
|
154
|
+
|
|
155
|
+
const summary = computed(() => selected.value.join(', '))
|
|
156
|
+
|
|
157
|
+
const selectAllLabel = computed(() => {
|
|
158
|
+
if (!props.selectAllCount) return t.value.all
|
|
159
|
+
const count = props.hasMore ? `Max: ${addOptions.value.length}` : addOptions.value.length
|
|
160
|
+
return `${t.value.all} (${count})`
|
|
161
|
+
})
|
|
162
|
+
|
|
163
|
+
let debounceId: ReturnType<typeof setTimeout> | undefined
|
|
164
|
+
watch(addSearch, (value) => {
|
|
165
|
+
clearTimeout(debounceId)
|
|
166
|
+
debounceId = setTimeout(() => emit('search', value), 500)
|
|
167
|
+
})
|
|
168
|
+
|
|
169
|
+
function close() {
|
|
170
|
+
isOpen.value = false
|
|
171
|
+
document.removeEventListener('click', onDocumentClick)
|
|
172
|
+
}
|
|
173
|
+
|
|
174
|
+
function onDocumentClick(event: MouseEvent) {
|
|
175
|
+
if (!rootRef.value?.contains(event.target as Node)) close()
|
|
176
|
+
}
|
|
177
|
+
|
|
178
|
+
async function toggle() {
|
|
179
|
+
if (props.disabled) return
|
|
180
|
+
if (isOpen.value) return close()
|
|
181
|
+
|
|
182
|
+
isOpen.value = true
|
|
183
|
+
rmPanelOpened(close)
|
|
184
|
+
document.addEventListener('click', onDocumentClick)
|
|
185
|
+
await nextTick()
|
|
186
|
+
addRef.value?.focus()
|
|
187
|
+
}
|
|
188
|
+
|
|
189
|
+
function commit(values: string[]) {
|
|
190
|
+
selected.value = values
|
|
191
|
+
emit('change', values)
|
|
192
|
+
}
|
|
193
|
+
|
|
194
|
+
function add(option: string) {
|
|
195
|
+
activePreset.value = undefined
|
|
196
|
+
commit([...selected.value, option])
|
|
197
|
+
}
|
|
198
|
+
|
|
199
|
+
function remove(option: string) {
|
|
200
|
+
activePreset.value = undefined
|
|
201
|
+
commit(selected.value.filter(value => value !== option))
|
|
202
|
+
}
|
|
203
|
+
|
|
204
|
+
function addAll() {
|
|
205
|
+
activePreset.value = undefined
|
|
206
|
+
commit([...selected.value, ...addOptions.value])
|
|
207
|
+
}
|
|
208
|
+
|
|
209
|
+
function clearAll() {
|
|
210
|
+
activePreset.value = undefined
|
|
211
|
+
commit([])
|
|
212
|
+
}
|
|
213
|
+
|
|
214
|
+
/** Une selection rapide remplace la selection : elle ne s'y ajoute pas. */
|
|
215
|
+
function applyPreset(preset: RmComplexSelectPreset) {
|
|
216
|
+
if (activePreset.value === preset.label) {
|
|
217
|
+
clearAll()
|
|
218
|
+
return
|
|
219
|
+
}
|
|
220
|
+
commit([...new Set(preset.values)])
|
|
221
|
+
activePreset.value = preset.label
|
|
222
|
+
}
|
|
223
|
+
|
|
224
|
+
let unregister: (() => void) | undefined
|
|
225
|
+
onMounted(() => {
|
|
226
|
+
unregister = rmPanelRegister(close)
|
|
227
|
+
})
|
|
228
|
+
|
|
229
|
+
onUnmounted(() => {
|
|
230
|
+
unregister?.()
|
|
231
|
+
clearTimeout(debounceId)
|
|
232
|
+
document.removeEventListener('click', onDocumentClick)
|
|
233
|
+
})
|
|
234
|
+
</script>
|
|
235
|
+
|
|
236
|
+
<template>
|
|
237
|
+
<div ref="rootRef" class="rm-csel" @keydown.escape="close">
|
|
238
|
+
<p class="rm-csel__label">
|
|
239
|
+
{{ label }}
|
|
240
|
+
<button v-if="labelInfo" type="button" class="rm-csel__info" @click="emit('openInfo')">
|
|
241
|
+
<RmIcon name="Info" :size="14" />
|
|
242
|
+
</button>
|
|
243
|
+
</p>
|
|
244
|
+
|
|
245
|
+
<button
|
|
246
|
+
type="button"
|
|
247
|
+
class="rm-csel__field"
|
|
248
|
+
:class="{ 'is-open': isOpen, 'is-disabled': disabled }"
|
|
249
|
+
:disabled="disabled"
|
|
250
|
+
:aria-expanded="isOpen"
|
|
251
|
+
aria-haspopup="true"
|
|
252
|
+
@click="toggle"
|
|
253
|
+
>
|
|
254
|
+
<RmTooltip :text="summary" :disabled="selected.length === 0" class="rm-csel__value-slot">
|
|
255
|
+
<span class="rm-csel__value" :class="{ 'is-empty': selected.length === 0 }">
|
|
256
|
+
{{ selected.length > 0 ? summary : emptyLabel || t.empty }}
|
|
257
|
+
</span>
|
|
258
|
+
</RmTooltip>
|
|
259
|
+
<span v-if="showAmount && selected.length > 0" class="rm-csel__count">
|
|
260
|
+
{{ selected.length > 99 ? '99+' : selected.length }}
|
|
261
|
+
</span>
|
|
262
|
+
<RmIcon name="CaretDown" :size="16" />
|
|
263
|
+
</button>
|
|
264
|
+
|
|
265
|
+
<div v-show="isOpen" class="rm-csel__panel" @click.stop>
|
|
266
|
+
<div class="rm-csel__column">
|
|
267
|
+
<div v-if="presets && presets.length > 0" class="rm-csel__presets">
|
|
268
|
+
<h2 class="rm-csel__section">{{ t.quick }}</h2>
|
|
269
|
+
<div class="rm-csel__pills">
|
|
270
|
+
<button
|
|
271
|
+
v-for="preset in presets"
|
|
272
|
+
:key="preset.label"
|
|
273
|
+
type="button"
|
|
274
|
+
class="rm-csel__pill"
|
|
275
|
+
:class="{ 'is-active': activePreset === preset.label }"
|
|
276
|
+
:aria-pressed="activePreset === preset.label"
|
|
277
|
+
@click="applyPreset(preset)"
|
|
278
|
+
>
|
|
279
|
+
{{ preset.label }}
|
|
280
|
+
</button>
|
|
281
|
+
</div>
|
|
282
|
+
</div>
|
|
283
|
+
|
|
284
|
+
<div class="rm-csel__head">
|
|
285
|
+
<h2 class="rm-csel__section">{{ presets && presets.length > 0 ? t.custom : t.add }}</h2>
|
|
286
|
+
<button
|
|
287
|
+
v-if="showSelectAll || selectAllCount"
|
|
288
|
+
type="button"
|
|
289
|
+
class="rm-csel__action"
|
|
290
|
+
:disabled="addOptions.length === 0"
|
|
291
|
+
@click="addAll"
|
|
292
|
+
>
|
|
293
|
+
{{ selectAllLabel }}
|
|
294
|
+
</button>
|
|
295
|
+
</div>
|
|
296
|
+
|
|
297
|
+
<div class="rm-csel__search">
|
|
298
|
+
<RmIcon name="MagnifyingGlass" :size="14" />
|
|
299
|
+
<input
|
|
300
|
+
ref="addRef"
|
|
301
|
+
v-model="addSearch"
|
|
302
|
+
type="search"
|
|
303
|
+
class="rm-csel__search-input"
|
|
304
|
+
:placeholder="addPlaceholder || t.searchAdd"
|
|
305
|
+
:aria-label="addPlaceholder || t.searchAdd"
|
|
306
|
+
>
|
|
307
|
+
</div>
|
|
308
|
+
|
|
309
|
+
<p v-if="loading" class="rm-csel__state" aria-busy="true">{{ t.loading }}</p>
|
|
310
|
+
<p v-else-if="addOptions.length === 0" class="rm-csel__state">
|
|
311
|
+
{{ emptyContent || t.notFound }}
|
|
312
|
+
</p>
|
|
313
|
+
<div v-else class="rm-csel__list">
|
|
314
|
+
<button
|
|
315
|
+
v-for="option in addOptions"
|
|
316
|
+
:key="option"
|
|
317
|
+
type="button"
|
|
318
|
+
class="rm-csel__option rm-csel__option--add"
|
|
319
|
+
@click="add(option)"
|
|
320
|
+
>
|
|
321
|
+
<RmIcon name="PlusCircle" :size="14" />
|
|
322
|
+
<span>{{ option }}</span>
|
|
323
|
+
</button>
|
|
324
|
+
</div>
|
|
325
|
+
</div>
|
|
326
|
+
|
|
327
|
+
<div class="rm-csel__column rm-csel__column--right">
|
|
328
|
+
<div class="rm-csel__head">
|
|
329
|
+
<h2 class="rm-csel__section">{{ t.current }}</h2>
|
|
330
|
+
<button
|
|
331
|
+
type="button"
|
|
332
|
+
class="rm-csel__action rm-csel__action--clear"
|
|
333
|
+
:disabled="selected.length === 0"
|
|
334
|
+
@click="clearAll"
|
|
335
|
+
>
|
|
336
|
+
{{ t.clear }}
|
|
337
|
+
</button>
|
|
338
|
+
</div>
|
|
339
|
+
|
|
340
|
+
<div class="rm-csel__search">
|
|
341
|
+
<RmIcon name="MagnifyingGlass" :size="14" />
|
|
342
|
+
<input
|
|
343
|
+
v-model="removeSearch"
|
|
344
|
+
type="search"
|
|
345
|
+
class="rm-csel__search-input"
|
|
346
|
+
:placeholder="removePlaceholder || t.searchDel"
|
|
347
|
+
:aria-label="removePlaceholder || t.searchDel"
|
|
348
|
+
>
|
|
349
|
+
</div>
|
|
350
|
+
|
|
351
|
+
<p v-if="selected.length === 0" class="rm-csel__state">{{ t.noSelection }}</p>
|
|
352
|
+
<p v-else-if="removeOptions.length === 0" class="rm-csel__state">
|
|
353
|
+
{{ emptyContent || t.notFound }}
|
|
354
|
+
</p>
|
|
355
|
+
<div v-else class="rm-csel__list">
|
|
356
|
+
<button
|
|
357
|
+
v-for="option in removeOptions"
|
|
358
|
+
:key="option"
|
|
359
|
+
type="button"
|
|
360
|
+
class="rm-csel__option rm-csel__option--remove"
|
|
361
|
+
@click="remove(option)"
|
|
362
|
+
>
|
|
363
|
+
<RmIcon name="MinusCircle" :size="16" />
|
|
364
|
+
<span>{{ option }}</span>
|
|
365
|
+
</button>
|
|
366
|
+
</div>
|
|
367
|
+
</div>
|
|
368
|
+
</div>
|
|
369
|
+
</div>
|
|
370
|
+
</template>
|
|
371
|
+
|
|
372
|
+
<style scoped>
|
|
373
|
+
.rm-csel{align-items:flex-start;display:flex;flex-direction:column;gap:4px;position:relative}.rm-csel__label{align-items:center;color:var(--text-secondary);display:flex;font-size:var(--font-12,12px);gap:4px;line-height:14px}.rm-csel__info{background:none;border:none;color:var(--text-muted);cursor:pointer;display:flex;padding:0}.rm-csel__field{align-items:center;background:var(--bg-surface);border:1.5px solid var(--border-default);border-radius:var(--radius-md,8px);color:var(--text-primary);cursor:pointer;display:flex;font-family:inherit;font-size:var(--font-14,14px);font-weight:700;gap:4px;line-height:16px;padding:12px;text-align:left;width:196px}.rm-csel__field:hover:not(.is-disabled){border-color:rgba(var(--brand-rgb),.3)}.rm-csel__field.is-open{border-color:var(--color-primary)}.rm-csel__field.is-disabled{background:var(--bg-surface-2);color:var(--text-muted);cursor:not-allowed}.rm-csel__field:focus-visible{outline:2px solid var(--color-primary);outline-offset:2px}.rm-csel__value-slot{display:block;flex:1;min-width:0}.rm-csel__value{display:block;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.rm-csel__value.is-empty{color:var(--text-muted);font-style:italic;font-weight:400}.rm-csel__field :deep(svg){color:var(--text-secondary);flex-shrink:0}.rm-csel__count{align-items:center;background:rgba(var(--brand-rgb),.1);border-radius:50%;color:var(--color-primary);display:flex;flex-shrink:0;font-size:var(--font-12,12px);font-weight:600;height:20px;justify-content:center;width:20px}.rm-csel__panel{background:var(--bg-surface);border:1.5px solid var(--border-default);border-radius:var(--radius-lg,12px);box-shadow:var(--r-shadow-lg,0 8px 24px rgba(0,0,0,.12));box-sizing:border-box;display:flex;left:0;margin-top:8px;max-width:calc(100vw - 32px);position:absolute;top:100%;width:620px;z-index:12}.rm-csel__column{display:flex;flex:1;flex-direction:column;gap:8px;min-width:0;padding:16px}.rm-csel__column--right{background:var(--bg-surface-2);border-left:1px solid var(--border-soft);border-radius:0 var(--radius-lg,12px) var(--radius-lg,12px) 0}.rm-csel__presets{border-bottom:1px solid var(--border-soft);display:flex;flex-direction:column;gap:8px;padding-bottom:8px}.rm-csel__pills{display:flex;flex-wrap:wrap;gap:4px}.rm-csel__pill{background:var(--bg-surface);border:1px solid var(--border-default);border-radius:9999px;color:var(--text-secondary);cursor:pointer;font-family:inherit;font-size:var(--font-12,12px);padding:4px 10px}.rm-csel__pill.is-active,.rm-csel__pill:hover{border-color:var(--color-primary);color:var(--color-primary)}.rm-csel__pill.is-active{background:rgba(var(--brand-rgb),.1);font-weight:700}.rm-csel__head{align-items:center;display:flex;gap:8px;justify-content:space-between}.rm-csel__section{color:var(--text-secondary);font-size:var(--font-12,12px);font-weight:700;margin:0}.rm-csel__action{background:none;border:none;color:var(--color-primary);cursor:pointer;font-family:inherit;font-size:var(--font-12,12px);font-weight:600;padding:0}.rm-csel__action:disabled{color:var(--text-muted);cursor:not-allowed}.rm-csel__action:hover:not(:disabled){text-decoration:underline}.rm-csel__action--clear:not(:disabled){color:var(--color-danger)}.rm-csel__search{align-items:center;background:var(--bg-surface);border:1px solid var(--border-default);border-radius:var(--radius-md,8px);display:flex;gap:8px;padding:6px 10px}.rm-csel__search :deep(svg){color:var(--text-muted);flex-shrink:0}.rm-csel__search-input{background:none;border:none;color:var(--text-primary);font-family:inherit;font-size:var(--font-14,14px);width:100%}.rm-csel__search-input::-moz-placeholder{color:var(--text-muted);font-size:var(--font-12,12px)}.rm-csel__search-input::placeholder{color:var(--text-muted);font-size:var(--font-12,12px)}.rm-csel__search-input:focus-visible{outline:none}.rm-csel__state{color:var(--text-secondary);font-size:var(--font-14,14px);font-style:italic;padding-top:8px}.rm-csel__list{display:flex;flex-direction:column;gap:4px;height:260px;overflow-y:auto;scrollbar-width:thin}.rm-csel__option{align-items:flex-start;background:none;border:none;border-radius:var(--radius-sm,4px);color:var(--text-primary);cursor:pointer;display:flex;font-family:inherit;font-size:var(--font-14,14px);gap:8px;line-height:160%;padding:2px 4px;text-align:left}.rm-csel__option :deep(svg){flex-shrink:0;margin-top:4px}.rm-csel__option:hover{background:rgba(var(--brand-rgb),.05)}.rm-csel__option:focus-visible{outline:2px solid var(--color-primary);outline-offset:-2px}.rm-csel__option--add :deep(svg){color:var(--color-primary)}.rm-csel__option--remove :deep(svg){color:var(--color-danger)}@media (max-width:767px){.rm-csel__panel{flex-direction:column;width:calc(100vw - 32px)}.rm-csel__column--right{border-left:none;border-top:1px solid var(--border-soft)}.rm-csel__list{height:180px}}
|
|
374
|
+
</style>
|
|
@@ -26,7 +26,8 @@
|
|
|
26
26
|
JSON de locale au montage.
|
|
27
27
|
-->
|
|
28
28
|
<script setup lang="ts">
|
|
29
|
-
import { computed, nextTick, onUnmounted, ref, watch } from 'vue'
|
|
29
|
+
import { computed, nextTick, onMounted, onUnmounted, ref, watch } from 'vue'
|
|
30
|
+
import { rmPanelOpened, rmPanelRegister } from '../utils/panels'
|
|
30
31
|
|
|
31
32
|
const props = withDefaults(defineProps<{
|
|
32
33
|
/** Intitule pose au-dessus du champ. */
|
|
@@ -120,6 +121,7 @@ async function toggle() {
|
|
|
120
121
|
if (isOpen.value) return close()
|
|
121
122
|
|
|
122
123
|
isOpen.value = true
|
|
124
|
+
rmPanelOpened(close)
|
|
123
125
|
searchTerm.value = ''
|
|
124
126
|
activeIndex.value = props.options.indexOf(selected.value ?? '')
|
|
125
127
|
document.addEventListener('click', onDocumentClick)
|
|
@@ -155,7 +157,13 @@ function onKeydown(event: KeyboardEvent) {
|
|
|
155
157
|
}
|
|
156
158
|
}
|
|
157
159
|
|
|
160
|
+
let unregister: (() => void) | undefined
|
|
161
|
+
onMounted(() => {
|
|
162
|
+
unregister = rmPanelRegister(close)
|
|
163
|
+
})
|
|
164
|
+
|
|
158
165
|
onUnmounted(() => {
|
|
166
|
+
unregister?.()
|
|
159
167
|
clearTimeout(debounceId)
|
|
160
168
|
document.removeEventListener('click', onDocumentClick)
|
|
161
169
|
})
|
|
@@ -172,7 +180,7 @@ onUnmounted(() => {
|
|
|
172
180
|
:disabled="disabled"
|
|
173
181
|
:aria-expanded="isOpen"
|
|
174
182
|
aria-haspopup="listbox"
|
|
175
|
-
@click
|
|
183
|
+
@click="toggle"
|
|
176
184
|
>
|
|
177
185
|
<RmTooltip :text="selected ?? ''" :disabled="!selected" class="rm-dsel__value-slot">
|
|
178
186
|
<span class="rm-dsel__value" :class="{ 'is-empty': !selected }">
|
|
@@ -275,5 +275,5 @@ onBeforeUnmount(() => {
|
|
|
275
275
|
</template>
|
|
276
276
|
|
|
277
277
|
<style scoped>
|
|
278
|
-
.rm-fbar{margin-inline:calc((min(var(--oip-content-max, 100%), 100%) - var(--oip-main-w, 100%))/2);position:sticky;width:var(--oip-main-w,100%);z-index:91;--rm-fbar-field-h:32px;backdrop-filter:blur(12px);background:rgba(245,245,249,.8);border-bottom:1px solid var(--border-default);display:flex;flex-direction:column;font-family:var(--font-sans)}.rm-fbar__views{align-items:center;display:flex;flex:0 0 auto}.rm-fbar__views:empty{display:none}.rm-fbar__row{align-items:flex-start;display:flex;gap:12px;padding-block:8px;padding-inline:max(32px,(100% - var(--oip-content-max,100%))/2 + 32px)}.rm-fbar--open .rm-fbar__row:not(:has(~.rm-fbar__rail-row)){border-bottom:1px solid var(--border-default)}.rm-fbar__toggle :deep(p),.rm-fbar__toggle :deep(span){font-size:inherit;font-weight:inherit;line-height:inherit;margin:0}.rm-fbar__toggle{align-items:center;background:var(--bg-surface);border:1px solid var(--border-default);border-radius:var(--radius-pill);color:var(--text-primary);cursor:pointer;display:flex;flex:0 0 auto;font-family:inherit;font-size:var(--font-14);font-weight:var(--weight-medium);gap:6px;height:var(--rm-fbar-field-h);justify-content:center;padding:0 14px}.rm-fbar__toggle:hover{background:var(--bg-surface-3)}.rm-fbar__toggle.is-active,.rm-fbar__toggle.is-active:hover{background:var(--color-primary);border-color:var(--color-primary);color:var(--color-text-inverse)}.rm-fbar__toggle.is-active .rm-fbar__badge{background:var(--color-text-inverse);color:var(--color-primary)}.rm-fbar__badge{align-items:center;background:var(--color-primary);border-radius:16px;color:var(--color-text-inverse);display:inline-flex;font-size:var(--font-11);font-weight:var(--weight-bold);justify-content:center;min-width:18px;padding:0 5px}.rm-fbar__view{align-items:center;display:flex;flex:0 0 auto}.rm-fbar__advanced{align-items:center;background:none;border:none;border-left:1px solid var(--border-default);color:var(--color-primary);cursor:pointer;display:inline-flex;font-family:inherit;font-size:var(--font-13);font-weight:var(--weight-medium);height:var(--rm-fbar-field-h);padding:0 0 0 12px;position:absolute;right:14px;text-decoration-line:underline;top:0;white-space:nowrap;z-index:2}.rm-fbar__advanced.is-active,.rm-fbar__advanced:hover{color:var(--color-primary-hover,var(--color-primary));text-decoration-thickness:2px}.rm-fbar__rail-row{display:flex;padding-bottom:8px;padding-inline:max(32px,(100% - var(--oip-content-max,100%))/2 + 32px)}.rm-fbar--open .rm-fbar__rail-row{border-bottom:1px solid var(--border-default)}.rm-fbar__rail{align-items:center;display:flex;flex:0 1 auto;min-width:0;overflow-x:auto;scrollbar-width:thin}.rm-fbar__rail:empty{display:none}.rm-fbar__search{align-items:center;display:flex;flex:1 1 auto;gap:8px;min-width:0;position:relative}.rm-fbar__search:empty{display:none}.rm-fbar__search :deep(.search-bar-wrapper){flex:1 1 auto;min-width:0}.rm-fbar__search :deep(.search-bar){background:var(--bg-surface);box-sizing:border-box;display:flex;height:var(--rm-fbar-field-h);width:100%}.rm-fbar__search :deep(.filters_input_search){border-radius:var(--radius-pill);box-sizing:border-box;height:auto;min-height:var(--rm-fbar-field-h);padding-right:calc(var(--rm-fbar-advanced-w, 0px) + 12px);width:100%}.rm-fbar__search :deep(.research_tags:not(:has(*))){display:none}.rm-fbar__search :deep(.select_shortcut){box-sizing:border-box;font-size:var(--font-11);height:24px;padding-block:0}.rm-fbar__search :deep(.select_shortcut:hover){background:var(--bg-surface-3)!important;border-color:var(--border-default)!important;color:inherit!important}.rm-fbar__search :deep(.select_shortcut:hover svg){color:inherit!important}.rm-fbar__search :deep(.remove_search_section){border-left:none;border-radius:0 var(--radius-pill) var(--radius-pill) 0}.rm-fbar__search :deep(.remove_search_section:hover){background:transparent!important}.rm-fbar__search :deep(.remove_search_section:hover svg){color:var(--text-primary)!important}.rm-fbar__search :deep(.filters_input_search.no_bottom){border-bottom:1.5px solid var(--color-primary)!important;border-radius:var(--radius-pill)}.rm-fbar__search :deep(.search_suggestions){border:1px solid var(--border-default);border-radius:var(--radius-2xl);box-shadow:var(--shadow-lg);left:0;padding:6px;right:0;top:calc(100% + 6px);width:auto}.rm-fbar__search :deep(.sugg_container>*){border-radius:var(--radius-lg)}.rm-fbar__search :deep(.sugg_container>.selected){background:color-mix(in srgb,var(--color-primary) 6%,transparent)!important}.rm-fbar__panel{--rm-filter-col:224px;--rm-fbar-panel-field-h:40px;align-items:end;display:grid;gap:
|
|
278
|
+
.rm-fbar{margin-inline:calc((min(var(--oip-content-max, 100%), 100%) - var(--oip-main-w, 100%))/2);position:sticky;width:var(--oip-main-w,100%);z-index:91;--rm-fbar-field-h:32px;backdrop-filter:blur(12px);background:rgba(245,245,249,.8);border-bottom:1px solid var(--border-default);display:flex;flex-direction:column;font-family:var(--font-sans)}.rm-fbar__views{align-items:center;display:flex;flex:0 0 auto}.rm-fbar__views:empty{display:none}.rm-fbar__row{align-items:flex-start;display:flex;gap:12px;padding-block:8px;padding-inline:max(32px,(100% - var(--oip-content-max,100%))/2 + 32px)}.rm-fbar--open .rm-fbar__row:not(:has(~.rm-fbar__rail-row)){border-bottom:1px solid var(--border-default)}.rm-fbar__toggle :deep(p),.rm-fbar__toggle :deep(span){font-size:inherit;font-weight:inherit;line-height:inherit;margin:0}.rm-fbar__toggle{align-items:center;background:var(--bg-surface);border:1px solid var(--border-default);border-radius:var(--radius-pill);color:var(--text-primary);cursor:pointer;display:flex;flex:0 0 auto;font-family:inherit;font-size:var(--font-14);font-weight:var(--weight-medium);gap:6px;height:var(--rm-fbar-field-h);justify-content:center;padding:0 14px}.rm-fbar__toggle:hover{background:var(--bg-surface-3)}.rm-fbar__toggle.is-active,.rm-fbar__toggle.is-active:hover{background:var(--color-primary);border-color:var(--color-primary);color:var(--color-text-inverse)}.rm-fbar__toggle.is-active .rm-fbar__badge{background:var(--color-text-inverse);color:var(--color-primary)}.rm-fbar__badge{align-items:center;background:var(--color-primary);border-radius:16px;color:var(--color-text-inverse);display:inline-flex;font-size:var(--font-11);font-weight:var(--weight-bold);justify-content:center;min-width:18px;padding:0 5px}.rm-fbar__view{align-items:center;display:flex;flex:0 0 auto}.rm-fbar__advanced{align-items:center;background:none;border:none;border-left:1px solid var(--border-default);color:var(--color-primary);cursor:pointer;display:inline-flex;font-family:inherit;font-size:var(--font-13);font-weight:var(--weight-medium);height:var(--rm-fbar-field-h);padding:0 0 0 12px;position:absolute;right:14px;text-decoration-line:underline;top:0;white-space:nowrap;z-index:2}.rm-fbar__advanced.is-active,.rm-fbar__advanced:hover{color:var(--color-primary-hover,var(--color-primary));text-decoration-thickness:2px}.rm-fbar__rail-row{display:flex;padding-bottom:8px;padding-inline:max(32px,(100% - var(--oip-content-max,100%))/2 + 32px)}.rm-fbar--open .rm-fbar__rail-row{border-bottom:1px solid var(--border-default)}.rm-fbar__rail{align-items:center;display:flex;flex:0 1 auto;min-width:0;overflow-x:auto;scrollbar-width:thin}.rm-fbar__rail:empty{display:none}.rm-fbar__search{align-items:center;display:flex;flex:1 1 auto;gap:8px;min-width:0;position:relative}.rm-fbar__search:empty{display:none}.rm-fbar__search :deep(.search-bar-wrapper){flex:1 1 auto;min-width:0}.rm-fbar__search :deep(.search-bar){background:var(--bg-surface);box-sizing:border-box;display:flex;height:var(--rm-fbar-field-h);width:100%}.rm-fbar__search :deep(.filters_input_search){border-radius:var(--radius-pill);box-sizing:border-box;height:auto;min-height:var(--rm-fbar-field-h);padding-right:calc(var(--rm-fbar-advanced-w, 0px) + 12px);width:100%}.rm-fbar__search :deep(.research_tags:not(:has(*))){display:none}.rm-fbar__search :deep(.select_shortcut){box-sizing:border-box;font-size:var(--font-11);height:24px;padding-block:0}.rm-fbar__search :deep(.select_shortcut:hover){background:var(--bg-surface-3)!important;border-color:var(--border-default)!important;color:inherit!important}.rm-fbar__search :deep(.select_shortcut:hover svg){color:inherit!important}.rm-fbar__search :deep(.remove_search_section){border-left:none;border-radius:0 var(--radius-pill) var(--radius-pill) 0}.rm-fbar__search :deep(.remove_search_section:hover){background:transparent!important}.rm-fbar__search :deep(.remove_search_section:hover svg){color:var(--text-primary)!important}.rm-fbar__search :deep(.filters_input_search.no_bottom){border-bottom:1.5px solid var(--color-primary)!important;border-radius:var(--radius-pill)}.rm-fbar__search :deep(.search_suggestions){border:1px solid var(--border-default);border-radius:var(--radius-2xl);box-shadow:var(--shadow-lg);left:0;padding:6px;right:0;top:calc(100% + 6px);width:auto}.rm-fbar__search :deep(.sugg_container>*){border-radius:var(--radius-lg)}.rm-fbar__search :deep(.sugg_container>.selected){background:color-mix(in srgb,var(--color-primary) 6%,transparent)!important}.rm-fbar__panel{--rm-filter-col:224px;--rm-fbar-panel-field-h:40px;align-items:end;display:grid;gap:8px;grid-template-columns:repeat(auto-fit,minmax(0,var(--rm-filter-col)));justify-content:center;padding-block:16px 20px;padding-inline:56px}.rm-fbar__panel--wide{align-items:stretch;display:flex;flex-direction:column;gap:12px}.rm-fbar__filters{display:contents}.rm-fbar__filters :deep(.filter-chip),.rm-fbar__filters :deep(.filter-complex__trigger),.rm-fbar__filters :deep(.rm-number__box){border-radius:var(--radius-lg);height:var(--rm-fbar-panel-field-h);width:100%}.rm-fbar__panel-head{align-items:baseline;display:flex;gap:16px;grid-column:1/-1;width:100%}.rm-fbar__customize{grid-column:1/-1}.rm-fbar__panel :deep(.filters_row_break){grid-column:1/-1}.rm-fbar__panel-title{font-size:var(--font-18);font-weight:800;margin:0}.rm-fbar__action{background:none;border:none;cursor:pointer;font-family:inherit;font-size:var(--font-14);font-weight:var(--weight-medium);padding:0;text-decoration-line:underline}.rm-fbar__action--save{color:var(--color-primary)}.rm-fbar__action--clear{color:var(--color-danger)}.rm-fbar__action--clear:hover{opacity:.8;text-decoration-thickness:2px}
|
|
279
279
|
</style>
|
|
@@ -24,7 +24,8 @@
|
|
|
24
24
|
identifiant cassait des que la liste etait filtree.
|
|
25
25
|
-->
|
|
26
26
|
<script setup lang="ts">
|
|
27
|
-
import { computed, nextTick, onUnmounted, ref, watch } from 'vue'
|
|
27
|
+
import { computed, nextTick, onMounted, onUnmounted, ref, watch } from 'vue'
|
|
28
|
+
import { rmPanelOpened, rmPanelRegister } from '../utils/panels'
|
|
28
29
|
|
|
29
30
|
const props = withDefaults(defineProps<{
|
|
30
31
|
/** Intitule pose au-dessus du champ. */
|
|
@@ -134,6 +135,7 @@ async function toggle() {
|
|
|
134
135
|
if (isOpen.value) return close()
|
|
135
136
|
|
|
136
137
|
isOpen.value = true
|
|
138
|
+
rmPanelOpened(close)
|
|
137
139
|
searchTerm.value = ''
|
|
138
140
|
document.addEventListener('click', onDocumentClick)
|
|
139
141
|
if (!props.search) return
|
|
@@ -156,7 +158,13 @@ function toggleAll() {
|
|
|
156
158
|
commit(allSelected.value ? [] : [...props.options])
|
|
157
159
|
}
|
|
158
160
|
|
|
161
|
+
let unregister: (() => void) | undefined
|
|
162
|
+
onMounted(() => {
|
|
163
|
+
unregister = rmPanelRegister(close)
|
|
164
|
+
})
|
|
165
|
+
|
|
159
166
|
onUnmounted(() => {
|
|
167
|
+
unregister?.()
|
|
160
168
|
clearTimeout(debounceId)
|
|
161
169
|
document.removeEventListener('click', onDocumentClick)
|
|
162
170
|
})
|
|
@@ -178,7 +186,7 @@ onUnmounted(() => {
|
|
|
178
186
|
:disabled="disabled"
|
|
179
187
|
:aria-expanded="isOpen"
|
|
180
188
|
aria-haspopup="true"
|
|
181
|
-
@click
|
|
189
|
+
@click="toggle"
|
|
182
190
|
>
|
|
183
191
|
<RmTooltip :text="summary" :disabled="selected.length === 0" class="rm-msel__value-slot">
|
|
184
192
|
<span class="rm-msel__value" :class="{ 'is-empty': selected.length === 0 }">
|
|
@@ -7,9 +7,11 @@
|
|
|
7
7
|
enregistrees, basculer sur une vue favorite, ouvrir le reste (toutes les
|
|
8
8
|
vues, enregistrer, et ce que la page ajoute).
|
|
9
9
|
|
|
10
|
-
Un point
|
|
11
|
-
|
|
12
|
-
|
|
10
|
+
Un point pulse a droite du nom des qu'il y a un etat a dire : vert quand une
|
|
11
|
+
vue est posee, orange quand l'ecran ne correspond plus a cette vue. Le second
|
|
12
|
+
couvre le premier, parce qu'une modification non enregistree est ce qui se
|
|
13
|
+
perd si on ne le voit pas. Meme forme que le point du rail : un seul signe a
|
|
14
|
+
apprendre pour les deux endroits ou l'etat d'une vue se lit.
|
|
13
15
|
|
|
14
16
|
La pastille ne connait ni l'API ni le magasin de vues : elle recoit une
|
|
15
17
|
liste et emet ce que l'utilisateur demande.
|
|
@@ -74,6 +76,7 @@ const WORDS = {
|
|
|
74
76
|
favorites: 'Favoris',
|
|
75
77
|
actions: 'Actions',
|
|
76
78
|
unsaved: 'Modifications non enregistrées',
|
|
79
|
+
applied: 'Vue appliquée',
|
|
77
80
|
save: 'Sauvegarder',
|
|
78
81
|
aria: 'Vue affichée',
|
|
79
82
|
},
|
|
@@ -83,6 +86,7 @@ const WORDS = {
|
|
|
83
86
|
favorites: 'Favorites',
|
|
84
87
|
actions: 'Actions',
|
|
85
88
|
unsaved: 'Unsaved changes',
|
|
89
|
+
applied: 'View applied',
|
|
86
90
|
save: 'Save',
|
|
87
91
|
aria: 'Current view',
|
|
88
92
|
},
|
|
@@ -142,7 +146,18 @@ onBeforeUnmount(() => {
|
|
|
142
146
|
<RmIcon name="BookmarkSimple" :size="16" class="rm-vpill__icon" />
|
|
143
147
|
<span class="rm-vpill__key">{{ t.key }}</span>
|
|
144
148
|
<span class="rm-vpill__value">{{ label }}</span>
|
|
145
|
-
<span
|
|
149
|
+
<span
|
|
150
|
+
v-if="dirty"
|
|
151
|
+
class="rm-vpill__dot rm-vpill__dot--unsaved"
|
|
152
|
+
:title="t.unsaved"
|
|
153
|
+
aria-hidden="true"
|
|
154
|
+
/>
|
|
155
|
+
<span
|
|
156
|
+
v-else-if="viewName"
|
|
157
|
+
class="rm-vpill__dot rm-vpill__dot--applied"
|
|
158
|
+
:title="t.applied"
|
|
159
|
+
aria-hidden="true"
|
|
160
|
+
/>
|
|
146
161
|
<RmIcon class="rm-vpill__caret" name="CaretDown" :size="14" />
|
|
147
162
|
</button>
|
|
148
163
|
|
|
@@ -194,5 +209,5 @@ onBeforeUnmount(() => {
|
|
|
194
209
|
</template>
|
|
195
210
|
|
|
196
211
|
<style scoped>
|
|
197
|
-
.rm-vpill{position:relative}.rm-vpill,.rm-vpill__pill{align-items:center;display:flex}.rm-vpill__pill{background:var(--bg-surface);border:1px solid var(--border-default);border-radius:var(--radius-pill);color:var(--text-primary);cursor:pointer;font-family:var(--font-sans);font-size:var(--font-14);font-weight:var(--weight-medium);gap:6px;height:var(--rm-fbar-field-h,32px);padding:0 14px;white-space:nowrap}.rm-vpill__pill:hover{background:var(--bg-surface-3)}.rm-vpill__pill.is-open{border-color:var(--color-primary);color:var(--color-primary)}.rm-vpill__icon{color:currentColor;flex-shrink:0}.rm-vpill__key{color:var(--text-muted);font-weight:var(--weight-normal)}.rm-vpill__value{max-width:220px;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.rm-vpill__pill.has-unsaved{border-color:var(--color-warning)}.rm-vpill__dot{animation:rm-vpill-pulse 2s ease-out infinite;background:var(--color-
|
|
212
|
+
.rm-vpill{position:relative}.rm-vpill,.rm-vpill__pill{align-items:center;display:flex}.rm-vpill__pill{background:var(--bg-surface);border:1px solid var(--border-default);border-radius:var(--radius-pill);color:var(--text-primary);cursor:pointer;font-family:var(--font-sans);font-size:var(--font-14);font-weight:var(--weight-medium);gap:6px;height:var(--rm-fbar-field-h,32px);padding:0 14px;white-space:nowrap}.rm-vpill__pill:hover{background:var(--bg-surface-3)}.rm-vpill__pill.is-open{border-color:var(--color-primary);color:var(--color-primary)}.rm-vpill__icon{color:currentColor;flex-shrink:0}.rm-vpill__key{color:var(--text-muted);font-weight:var(--weight-normal)}.rm-vpill__value{max-width:220px;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.rm-vpill__pill.has-unsaved{border-color:var(--color-warning)}.rm-vpill__dot{border-radius:50%;flex-shrink:0;height:8px;width:8px}.rm-vpill__dot--applied{animation:rm-vpill-pulse-applied 2s ease-out infinite;background:var(--color-success)}.rm-vpill__dot--unsaved{animation:rm-vpill-pulse 2s ease-out infinite;background:var(--color-warning)}@keyframes rm-vpill-pulse{0%{box-shadow:0 0 0 0 rgba(217,119,6,.6)}70%{box-shadow:0 0 0 6px rgba(217,119,6,0)}to{box-shadow:0 0 0 0 rgba(217,119,6,0)}}@keyframes rm-vpill-pulse-applied{0%{box-shadow:0 0 0 0 rgba(22,163,74,.55)}70%{box-shadow:0 0 0 6px rgba(22,163,74,0)}to{box-shadow:0 0 0 0 rgba(22,163,74,0)}}@media (prefers-reduced-motion:reduce){.rm-vpill__dot,.rm-vpill__unsaved-dot:before{animation:none}}.rm-vpill__caret{color:var(--text-muted);flex-shrink:0}.rm-vpill__menu{background:var(--bg-surface);border:1px solid var(--border-default);border-radius:8px;box-shadow:var(--shadow-lg);box-sizing:border-box;font-family:var(--font-sans);left:0;max-width:460px;min-width:320px;padding:6px;position:absolute;top:calc(100% + 6px);z-index:60}.rm-vpill__unsaved{align-items:center;background:var(--color-warning-bg);border-radius:var(--radius-md);color:var(--color-warning);display:flex;font-size:var(--font-12);gap:8px;padding:8px 12px}.rm-vpill__unsaved-dot{align-items:center;display:inline-flex;flex-shrink:0;height:14px;justify-content:center;width:14px}.rm-vpill__unsaved-dot:before{animation:rm-vpill-pulse 2s ease-out infinite;background:var(--color-warning);border-radius:50%;content:"";height:7px;width:7px}.rm-vpill__unsaved-label{flex:1;font-weight:var(--weight-semibold)}.rm-vpill__unsaved-cta{background:transparent;border:none;color:var(--color-warning);cursor:pointer;font-family:inherit;font-size:inherit;font-weight:var(--weight-bold);padding:0;text-decoration:underline;text-underline-offset:2px}.rm-vpill__unsaved-cta:hover{color:var(--text-primary)}.rm-vpill__divider{background:var(--border-soft);height:1px;margin:6px -6px}.rm-vpill__section{color:var(--text-muted);font-size:var(--font-10);font-weight:var(--weight-bold);letter-spacing:.08em;margin:0;padding:8px 12px 4px 34px;text-align:left;text-transform:uppercase}.rm-vpill__item{align-items:center;background:none;border:none;border-radius:var(--radius-md);color:var(--text-secondary);cursor:pointer;display:flex;font-family:inherit;font-size:var(--font-13);gap:8px;padding:8px 12px;text-align:left;transition:background .1s,color .1s;width:100%}.rm-vpill__item:hover{background:var(--bg-hover);color:var(--text-primary)}.rm-vpill__item.is-active{background:var(--bg-hover);color:var(--color-secondary);font-weight:var(--weight-semibold)}.rm-vpill__name{flex:1;min-width:0;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.rm-vpill__item--view .rm-vpill__check{color:var(--color-secondary);flex-shrink:0;opacity:0;transition:opacity .1s}.rm-vpill__item--view.is-active .rm-vpill__check{opacity:1}
|
|
198
213
|
</style>
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Inscrit un panneau. A appeler au montage, cote client seulement : sur le
|
|
3
|
+
* serveur le registre est partage par toutes les requetes et personne ne le
|
|
4
|
+
* vide.
|
|
5
|
+
*/
|
|
6
|
+
export declare function rmPanelRegister(close: () => void): () => boolean;
|
|
7
|
+
/** Ferme tous les panneaux sauf celui qui vient de s'ouvrir. */
|
|
8
|
+
export declare function rmPanelOpened(self: () => void): void;
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
const closers = /* @__PURE__ */ new Set();
|
|
2
|
+
export function rmPanelRegister(close) {
|
|
3
|
+
closers.add(close);
|
|
4
|
+
return () => closers.delete(close);
|
|
5
|
+
}
|
|
6
|
+
export function rmPanelOpened(self) {
|
|
7
|
+
closers.forEach((close) => {
|
|
8
|
+
if (close !== self) close();
|
|
9
|
+
});
|
|
10
|
+
}
|