@perspective-dev/viewer 5.3.0 → 5.3.1
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/cdn/perspective-viewer.js +8 -8
- package/dist/cdn/perspective-viewer.js.map +3 -3
- package/dist/css/blueprint.css +1 -0
- package/dist/css/botanical.css +1 -1
- package/dist/css/dracula.css +1 -1
- package/dist/css/eggplant.css +1 -0
- package/dist/css/gruvbox-dark.css +1 -1
- package/dist/css/gruvbox.css +1 -1
- package/dist/css/icons.css +1 -1
- package/dist/css/intl/de.css +1 -1
- package/dist/css/intl/es.css +1 -1
- package/dist/css/intl/fr.css +1 -1
- package/dist/css/intl/ja.css +1 -1
- package/dist/css/intl/pt.css +1 -1
- package/dist/css/intl/zh.css +1 -1
- package/dist/css/intl.css +1 -1
- package/dist/css/ledger.css +1 -0
- package/dist/css/monokai.css +1 -1
- package/dist/css/nord.css +1 -0
- package/dist/css/phosphor.css +1 -1
- package/dist/css/pro-dark.css +1 -1
- package/dist/css/pro.css +1 -1
- package/dist/css/solarized-dark.css +1 -1
- package/dist/css/solarized.css +1 -1
- package/dist/css/themes.css +1 -1
- package/dist/css/vaporwave.css +1 -1
- package/dist/css/velvet.css +1 -0
- package/dist/docs/perspective-docs.json +1 -1
- package/dist/esm/column-format.d.ts +16 -3
- package/dist/esm/perspective-viewer.inline.js +9 -9
- package/dist/esm/perspective-viewer.inline.js.map +3 -3
- package/dist/esm/perspective-viewer.js +8 -8
- package/dist/esm/perspective-viewer.js.map +3 -3
- package/dist/wasm/perspective-viewer.d.ts +16 -16
- package/dist/wasm/perspective-viewer.js +107 -103
- package/dist/wasm/perspective-viewer.wasm +0 -0
- package/dist/wasm/perspective-viewer.wasm.d.ts +16 -16
- package/package.json +1 -1
- package/src/css/column-settings-panel.css +19 -0
- package/src/css/column-style.css +82 -0
- package/src/css/containers/tabs.css +13 -3
- package/src/css/dom/select.css +19 -8
- package/src/css/plugin-selector.css +1 -0
- package/src/css/plugin-settings-panel.css +72 -0
- package/src/css/viewer.css +0 -5
- package/src/rust/agent/tools.rs +5 -2
- package/src/rust/components/column_settings_sidebar/style_tab.rs +296 -237
- package/src/rust/components/containers/control_group.rs +91 -0
- package/src/rust/components/containers/mod.rs +1 -0
- package/src/rust/components/containers/select.rs +8 -2
- package/src/rust/components/datetime_column_style/simple.rs +15 -4
- package/src/rust/components/datetime_column_style.rs +50 -10
- package/src/rust/components/plugin_tab.rs +125 -87
- package/src/rust/components/settings_panel.rs +1 -0
- package/src/rust/components/status_bar.rs +0 -1
- package/src/rust/components/style_controls/number_string_format/digits_section.rs +22 -10
- package/src/rust/components/style_controls/number_string_format/misc_section.rs +6 -2
- package/src/rust/components/style_controls/number_string_format/style_section.rs +1 -0
- package/src/rust/components/style_controls/number_string_format/types.rs +24 -0
- package/src/rust/components/style_controls/number_string_format.rs +37 -14
- package/src/rust/config/column_config_schema.rs +358 -27
- package/src/rust/config/datetime_column_style.rs +4 -21
- package/src/rust/config/number_string_format.rs +211 -18
- package/src/rust/presentation.rs +17 -0
- package/src/rust/queries/plugin_column_styles.rs +2 -2
- package/src/rust/renderer/dispatch.rs +34 -8
- package/src/rust/renderer/plugin_config.rs +55 -8
- package/src/themes/blueprint.css +190 -0
- package/src/themes/botanical.css +4 -17
- package/src/themes/defaults.css +2 -120
- package/src/themes/dracula.css +2 -14
- package/src/themes/eggplant.css +189 -0
- package/src/themes/gruvbox-dark.css +3 -15
- package/src/themes/gruvbox.css +1 -1
- package/src/themes/icons.css +1 -2
- package/src/themes/intl/de.css +23 -1
- package/src/themes/intl/es.css +23 -1
- package/src/themes/intl/fr.css +23 -1
- package/src/themes/intl/ja.css +23 -1
- package/src/themes/intl/pt.css +23 -1
- package/src/themes/intl/zh.css +23 -1
- package/src/themes/intl.css +26 -4
- package/src/themes/ledger.css +195 -0
- package/src/themes/monokai.css +2 -14
- package/src/themes/nord.css +186 -0
- package/src/themes/phosphor.css +2 -14
- package/src/themes/pro-dark.css +2 -16
- package/src/themes/pro.css +118 -0
- package/src/themes/solarized-dark.css +2 -16
- package/src/themes/themes.css +10 -5
- package/src/themes/vaporwave.css +2 -14
- package/src/themes/velvet.css +192 -0
- package/src/ts/column-format.ts +52 -2
- package/src/svg/dropdown-selector-light.svg +0 -3
- /package/dist/wasm/snippets/{perspective-viewer-39c3c3b28e3cbd48 → perspective-viewer-87bd21b215d0631a}/inline0.js +0 -0
- /package/dist/wasm/snippets/{perspective-viewer-39c3c3b28e3cbd48 → perspective-viewer-87bd21b215d0631a}/inline1.js +0 -0
- /package/dist/wasm/snippets/{perspective-viewer-39c3c3b28e3cbd48 → perspective-viewer-87bd21b215d0631a}/inline2.js +0 -0
- /package/dist/wasm/snippets/{perspective-viewer-39c3c3b28e3cbd48 → perspective-viewer-87bd21b215d0631a}/inline3.js +0 -0
- /package/dist/wasm/snippets/{perspective-viewer-39c3c3b28e3cbd48 → perspective-viewer-87bd21b215d0631a}/inline4.js +0 -0
- /package/dist/wasm/snippets/{perspective-viewer-39c3c3b28e3cbd48 → perspective-viewer-87bd21b215d0631a}/inline5.js +0 -0
|
@@ -22,6 +22,13 @@ pub struct DatetimeStyleSimpleProps {
|
|
|
22
22
|
pub enable_time_config: bool,
|
|
23
23
|
pub config: SimpleDatetimeStyleConfig,
|
|
24
24
|
|
|
25
|
+
/// The plugin-declared default preset for each style select.
|
|
26
|
+
#[prop_or(SimpleDatetimeFormat::Short)]
|
|
27
|
+
pub date_style_default: SimpleDatetimeFormat,
|
|
28
|
+
|
|
29
|
+
#[prop_or(SimpleDatetimeFormat::Medium)]
|
|
30
|
+
pub time_style_default: SimpleDatetimeFormat,
|
|
31
|
+
|
|
25
32
|
#[prop_or_default]
|
|
26
33
|
pub on_change: Callback<SimpleDatetimeStyleConfig>,
|
|
27
34
|
|
|
@@ -37,7 +44,10 @@ impl ModalLink<DatetimeStyleSimple> for DatetimeStyleSimpleProps {
|
|
|
37
44
|
|
|
38
45
|
impl PartialEq for DatetimeStyleSimpleProps {
|
|
39
46
|
fn eq(&self, other: &Self) -> bool {
|
|
40
|
-
self.enable_time_config == other.enable_time_config
|
|
47
|
+
self.enable_time_config == other.enable_time_config
|
|
48
|
+
&& self.config == other.config
|
|
49
|
+
&& self.date_style_default == other.date_style_default
|
|
50
|
+
&& self.time_style_default == other.time_style_default
|
|
41
51
|
}
|
|
42
52
|
}
|
|
43
53
|
|
|
@@ -69,12 +79,12 @@ impl Component for DatetimeStyleSimple {
|
|
|
69
79
|
fn update(&mut self, ctx: &Context<Self>, msg: Self::Message) -> bool {
|
|
70
80
|
match msg {
|
|
71
81
|
DatetimeStyleSimpleMsg::DateStyleChanged(format) => {
|
|
72
|
-
self.config.date_style = format.
|
|
82
|
+
self.config.date_style = format.unwrap_or(ctx.props().date_style_default);
|
|
73
83
|
self.dispatch_config(ctx);
|
|
74
84
|
true
|
|
75
85
|
},
|
|
76
86
|
DatetimeStyleSimpleMsg::TimeStyleChanged(format) => {
|
|
77
|
-
self.config.time_style = format.
|
|
87
|
+
self.config.time_style = format.unwrap_or(ctx.props().time_style_default);
|
|
78
88
|
self.dispatch_config(ctx);
|
|
79
89
|
true
|
|
80
90
|
},
|
|
@@ -99,13 +109,14 @@ impl Component for DatetimeStyleSimple {
|
|
|
99
109
|
label="date-style"
|
|
100
110
|
on_change={ctx.link().callback(DatetimeStyleSimpleMsg::DateStyleChanged)}
|
|
101
111
|
current_value={self.config.date_style}
|
|
112
|
+
default_value={ctx.props().date_style_default}
|
|
102
113
|
/>
|
|
103
114
|
if ctx.props().enable_time_config {
|
|
104
115
|
<SelectEnumField<SimpleDatetimeFormat>
|
|
105
116
|
label="time-style"
|
|
106
117
|
on_change={ctx.link().callback(DatetimeStyleSimpleMsg::TimeStyleChanged)}
|
|
107
118
|
current_value={self.config.time_style}
|
|
108
|
-
default_value={
|
|
119
|
+
default_value={ctx.props().time_style_default}
|
|
109
120
|
/>
|
|
110
121
|
}
|
|
111
122
|
</>
|
|
@@ -38,6 +38,9 @@ pub struct DatetimeColumnStyleProps {
|
|
|
38
38
|
pub enable_time_config: bool,
|
|
39
39
|
pub config: Option<DatetimeColumnStyleConfig>,
|
|
40
40
|
|
|
41
|
+
/// The active plugin's declared default `date_format`.
|
|
42
|
+
pub default_format: Rc<DatetimeFormatType>,
|
|
43
|
+
|
|
41
44
|
#[prop_or_default]
|
|
42
45
|
pub on_change: Callback<ColumnConfigFieldUpdate>,
|
|
43
46
|
|
|
@@ -57,7 +60,9 @@ impl ModalLink<DatetimeColumnStyle> for DatetimeColumnStyleProps {
|
|
|
57
60
|
|
|
58
61
|
impl PartialEq for DatetimeColumnStyleProps {
|
|
59
62
|
fn eq(&self, other: &Self) -> bool {
|
|
60
|
-
self.enable_time_config == other.enable_time_config
|
|
63
|
+
self.enable_time_config == other.enable_time_config
|
|
64
|
+
&& self.config == other.config
|
|
65
|
+
&& self.default_format == other.default_format
|
|
61
66
|
}
|
|
62
67
|
}
|
|
63
68
|
|
|
@@ -90,7 +95,9 @@ impl Component for DatetimeColumnStyle {
|
|
|
90
95
|
std::mem::swap(&mut self.config, &mut new_config);
|
|
91
96
|
rerender = true;
|
|
92
97
|
}
|
|
93
|
-
if old.enable_time_config != ctx.props().enable_time_config
|
|
98
|
+
if old.enable_time_config != ctx.props().enable_time_config
|
|
99
|
+
|| old.default_format != ctx.props().default_format
|
|
100
|
+
{
|
|
94
101
|
rerender = true;
|
|
95
102
|
}
|
|
96
103
|
rerender
|
|
@@ -99,22 +106,24 @@ impl Component for DatetimeColumnStyle {
|
|
|
99
106
|
fn update(&mut self, ctx: &Context<Self>, msg: Self::Message) -> bool {
|
|
100
107
|
match msg {
|
|
101
108
|
DatetimeColumnStyleMsg::TimezoneChanged(val) => {
|
|
109
|
+
let mut format = self.effective_format(ctx);
|
|
102
110
|
if Some(&*USER_TIMEZONE) != val.as_ref() {
|
|
103
|
-
*
|
|
111
|
+
*format.time_zone_mut() = val;
|
|
104
112
|
} else {
|
|
105
|
-
*
|
|
113
|
+
*format.time_zone_mut() = None;
|
|
106
114
|
}
|
|
107
115
|
|
|
116
|
+
self.set_format(ctx, format);
|
|
108
117
|
self.dispatch_config(ctx);
|
|
109
118
|
true
|
|
110
119
|
},
|
|
111
120
|
DatetimeColumnStyleMsg::SimpleDatetimeStyleConfigChanged(simple) => {
|
|
112
|
-
self.
|
|
121
|
+
self.set_format(ctx, DatetimeFormatType::Simple(simple));
|
|
113
122
|
self.dispatch_config(ctx);
|
|
114
123
|
true
|
|
115
124
|
},
|
|
116
125
|
DatetimeColumnStyleMsg::CustomDatetimeStyleConfigChanged(custom) => {
|
|
117
|
-
self.
|
|
126
|
+
self.set_format(ctx, DatetimeFormatType::Custom(custom));
|
|
118
127
|
self.dispatch_config(ctx);
|
|
119
128
|
true
|
|
120
129
|
},
|
|
@@ -122,6 +131,24 @@ impl Component for DatetimeColumnStyle {
|
|
|
122
131
|
}
|
|
123
132
|
|
|
124
133
|
fn view(&self, ctx: &Context<Self>) -> Html {
|
|
134
|
+
let format = self.effective_format(ctx);
|
|
135
|
+
let (date_style_default, time_style_default) = match &*ctx.props().default_format {
|
|
136
|
+
DatetimeFormatType::Simple(simple) => (simple.date_style, simple.time_style),
|
|
137
|
+
DatetimeFormatType::Custom(_) => {
|
|
138
|
+
(SimpleDatetimeFormat::Short, SimpleDatetimeFormat::Medium)
|
|
139
|
+
},
|
|
140
|
+
};
|
|
141
|
+
|
|
142
|
+
let simple_reset = {
|
|
143
|
+
let default_format = ctx.props().default_format.clone();
|
|
144
|
+
ctx.link().callback(move |_| {
|
|
145
|
+
DatetimeColumnStyleMsg::SimpleDatetimeStyleConfigChanged(match &*default_format {
|
|
146
|
+
DatetimeFormatType::Simple(simple) => simple.clone(),
|
|
147
|
+
DatetimeFormatType::Custom(_) => SimpleDatetimeStyleConfig::default(),
|
|
148
|
+
})
|
|
149
|
+
})
|
|
150
|
+
};
|
|
151
|
+
|
|
125
152
|
html! {
|
|
126
153
|
<>
|
|
127
154
|
<div id="column-style-container" class="datetime-column-style-container">
|
|
@@ -131,10 +158,10 @@ impl Component for DatetimeColumnStyle {
|
|
|
131
158
|
values={ALL_TIMEZONES.with(|x| (*x).clone())}
|
|
132
159
|
default_value={(*USER_TIMEZONE).clone()}
|
|
133
160
|
on_change={ctx.link().callback(DatetimeColumnStyleMsg::TimezoneChanged)}
|
|
134
|
-
current_value={
|
|
161
|
+
current_value={format.time_zone().as_ref().unwrap_or(&*USER_TIMEZONE).clone()}
|
|
135
162
|
/>
|
|
136
163
|
}
|
|
137
|
-
if let DatetimeFormatType::Simple(config) = &
|
|
164
|
+
if let DatetimeFormatType::Simple(config) = &format {
|
|
138
165
|
if ctx.props().enable_time_config {
|
|
139
166
|
<div class="row">
|
|
140
167
|
<button
|
|
@@ -149,15 +176,17 @@ impl Component for DatetimeColumnStyle {
|
|
|
149
176
|
enable_time_config={ctx.props().enable_time_config}
|
|
150
177
|
on_change={ctx.link().callback(DatetimeColumnStyleMsg::SimpleDatetimeStyleConfigChanged)}
|
|
151
178
|
config={config.clone()}
|
|
179
|
+
{date_style_default}
|
|
180
|
+
{time_style_default}
|
|
152
181
|
/>
|
|
153
|
-
} else if let DatetimeFormatType::Custom(config) = &
|
|
182
|
+
} else if let DatetimeFormatType::Custom(config) = &format {
|
|
154
183
|
if ctx.props().enable_time_config {
|
|
155
184
|
<div class="row">
|
|
156
185
|
<button
|
|
157
186
|
id="datetime_format"
|
|
158
187
|
data-title="Custom"
|
|
159
188
|
data-title-hover="Switch to Simple"
|
|
160
|
-
onclick={
|
|
189
|
+
onclick={simple_reset}
|
|
161
190
|
/>
|
|
162
191
|
</div>
|
|
163
192
|
}
|
|
@@ -201,6 +230,17 @@ static USER_TIMEZONE: LazyLock<String> = LazyLock::new(|| {
|
|
|
201
230
|
});
|
|
202
231
|
|
|
203
232
|
impl DatetimeColumnStyle {
|
|
233
|
+
fn effective_format(&self, ctx: &Context<Self>) -> DatetimeFormatType {
|
|
234
|
+
self.config
|
|
235
|
+
.date_format
|
|
236
|
+
.clone()
|
|
237
|
+
.unwrap_or_else(|| (*ctx.props().default_format).clone())
|
|
238
|
+
}
|
|
239
|
+
|
|
240
|
+
fn set_format(&mut self, ctx: &Context<Self>, format: DatetimeFormatType) {
|
|
241
|
+
self.config.date_format = (format != *ctx.props().default_format).then_some(format);
|
|
242
|
+
}
|
|
243
|
+
|
|
204
244
|
/// When this config has changed, we must signal the wrapper element.
|
|
205
245
|
fn dispatch_config(&self, ctx: &Context<Self>) {
|
|
206
246
|
let value = if self.config == DatetimeColumnStyleConfig::default() {
|
|
@@ -22,7 +22,9 @@ use yew::prelude::*;
|
|
|
22
22
|
use crate::components::column_settings_sidebar::style_tab::primitive_field::{
|
|
23
23
|
BoolField, ColorField, EnumField, NumberFieldPrimitive,
|
|
24
24
|
};
|
|
25
|
+
use crate::components::containers::control_group::ControlGroup;
|
|
25
26
|
use crate::config::ControlSpec;
|
|
27
|
+
use crate::presentation::Presentation;
|
|
26
28
|
use crate::queries::get_plugin_config_schema;
|
|
27
29
|
use crate::renderer::Renderer;
|
|
28
30
|
use crate::session::Session;
|
|
@@ -47,6 +49,7 @@ pub struct PluginTabProps {
|
|
|
47
49
|
pub plugin_config: PtrEqRc<serde_json::Map<String, serde_json::Value>>,
|
|
48
50
|
|
|
49
51
|
// State
|
|
52
|
+
pub presentation: Presentation,
|
|
50
53
|
pub renderer: Renderer,
|
|
51
54
|
pub session: Session,
|
|
52
55
|
}
|
|
@@ -95,98 +98,133 @@ pub fn PluginTab(props: &PluginTabProps) -> Html {
|
|
|
95
98
|
})
|
|
96
99
|
};
|
|
97
100
|
|
|
98
|
-
let
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
.filter_map(|spec| {
|
|
103
|
-
let component = match spec {
|
|
104
|
-
ControlSpec::Enum {
|
|
105
|
-
key,
|
|
106
|
-
variants,
|
|
107
|
-
default,
|
|
108
|
-
} => {
|
|
109
|
-
let current = raw_config
|
|
110
|
-
.get(&key)
|
|
111
|
-
.and_then(|v| v.as_str().map(|s| s.to_string()));
|
|
112
|
-
html! {
|
|
113
|
-
<EnumField
|
|
114
|
-
field_key={key}
|
|
115
|
-
{variants}
|
|
116
|
-
{default}
|
|
117
|
-
{current}
|
|
118
|
-
on_change={on_change.clone()}
|
|
119
|
-
/>
|
|
120
|
-
}
|
|
121
|
-
},
|
|
122
|
-
ControlSpec::Bool { key, default } => {
|
|
123
|
-
let current = raw_config.get(&key).and_then(|v| v.as_bool());
|
|
124
|
-
html! {
|
|
125
|
-
<BoolField
|
|
126
|
-
field_key={key}
|
|
127
|
-
{default}
|
|
128
|
-
{current}
|
|
129
|
-
on_change={on_change.clone()}
|
|
130
|
-
/>
|
|
131
|
-
}
|
|
132
|
-
},
|
|
133
|
-
ControlSpec::Color { key, default } => {
|
|
134
|
-
let current = raw_config
|
|
135
|
-
.get(&key)
|
|
136
|
-
.and_then(|v| v.as_str().map(|s| s.to_string()));
|
|
137
|
-
html! {
|
|
138
|
-
<ColorField
|
|
139
|
-
field_key={key}
|
|
140
|
-
{default}
|
|
141
|
-
{current}
|
|
142
|
-
on_change={on_change.clone()}
|
|
143
|
-
/>
|
|
144
|
-
}
|
|
145
|
-
},
|
|
146
|
-
ControlSpec::Number {
|
|
147
|
-
key,
|
|
148
|
-
default,
|
|
149
|
-
min,
|
|
150
|
-
max,
|
|
151
|
-
step,
|
|
152
|
-
include,
|
|
153
|
-
} => {
|
|
154
|
-
let current = raw_config.get(&key).and_then(|v| v.as_f64());
|
|
155
|
-
html! {
|
|
156
|
-
<NumberFieldPrimitive
|
|
157
|
-
field_key={key}
|
|
158
|
-
{default}
|
|
159
|
-
{current}
|
|
160
|
-
{min}
|
|
161
|
-
{max}
|
|
162
|
-
{step}
|
|
163
|
-
{include}
|
|
164
|
-
on_change={on_change.clone()}
|
|
165
|
-
/>
|
|
166
|
-
}
|
|
167
|
-
},
|
|
168
|
-
// Column-scoped variants don't apply to
|
|
169
|
-
// plugin-level config; drop silently.
|
|
170
|
-
ControlSpec::AggregateDepth
|
|
171
|
-
| ControlSpec::NumberSeriesStyle { .. }
|
|
172
|
-
| ControlSpec::DatetimeFormat
|
|
173
|
-
| ControlSpec::StringFormat
|
|
174
|
-
| ControlSpec::Symbols { .. }
|
|
175
|
-
| ControlSpec::NumberFormat
|
|
176
|
-
| ControlSpec::String { .. }
|
|
177
|
-
| ControlSpec::Palette { .. }
|
|
178
|
-
| ControlSpec::GradientStops { .. } => {
|
|
179
|
-
return None;
|
|
180
|
-
},
|
|
181
|
-
};
|
|
182
|
-
|
|
183
|
-
Some(html! { <fieldset class="style-control">{ component }</fieldset> })
|
|
101
|
+
let on_group_toggle = {
|
|
102
|
+
let presentation = props.presentation.clone();
|
|
103
|
+
yew::Callback::from(move |(key, open): (String, bool)| {
|
|
104
|
+
presentation.set_control_group_collapsed(&key, !open);
|
|
184
105
|
})
|
|
185
|
-
|
|
106
|
+
};
|
|
186
107
|
|
|
108
|
+
let raw_config = &*props.plugin_config;
|
|
109
|
+
let components = render_specs(
|
|
110
|
+
&schema,
|
|
111
|
+
raw_config,
|
|
112
|
+
&on_change,
|
|
113
|
+
&props.presentation,
|
|
114
|
+
&on_group_toggle,
|
|
115
|
+
);
|
|
187
116
|
html! {
|
|
188
117
|
<div id="plugin-tab" class="sidebar_column scrollable">
|
|
189
118
|
<div id="plugin-config-container" class="tab-section">{ components }</div>
|
|
190
119
|
</div>
|
|
191
120
|
}
|
|
192
121
|
}
|
|
122
|
+
|
|
123
|
+
fn render_specs(
|
|
124
|
+
specs: &[ControlSpec],
|
|
125
|
+
raw_config: &serde_json::Map<String, serde_json::Value>,
|
|
126
|
+
on_change: &Callback<crate::config::ColumnConfigFieldUpdate>,
|
|
127
|
+
presentation: &Presentation,
|
|
128
|
+
on_group_toggle: &Callback<(String, bool)>,
|
|
129
|
+
) -> Vec<Html> {
|
|
130
|
+
specs
|
|
131
|
+
.iter()
|
|
132
|
+
.filter_map(|spec| match spec {
|
|
133
|
+
ControlSpec::Group { key, fields } => {
|
|
134
|
+
let children =
|
|
135
|
+
render_specs(fields, raw_config, on_change, presentation, on_group_toggle);
|
|
136
|
+
|
|
137
|
+
(!children.is_empty()).then(|| {
|
|
138
|
+
html! {
|
|
139
|
+
<ControlGroup
|
|
140
|
+
key={format!("group::{key}")}
|
|
141
|
+
group_key={key.clone()}
|
|
142
|
+
open={!presentation.is_control_group_collapsed(key)}
|
|
143
|
+
on_toggle={on_group_toggle.clone()}
|
|
144
|
+
>
|
|
145
|
+
{ children }
|
|
146
|
+
</ControlGroup>
|
|
147
|
+
}
|
|
148
|
+
})
|
|
149
|
+
},
|
|
150
|
+
leaf => {
|
|
151
|
+
let key = leaf.serialized_keys().join("+");
|
|
152
|
+
let component = render_leaf(leaf, raw_config, on_change)?;
|
|
153
|
+
Some(html! { <fieldset class="style-control" {key}>{ component }</fieldset> })
|
|
154
|
+
},
|
|
155
|
+
})
|
|
156
|
+
.collect_vec()
|
|
157
|
+
}
|
|
158
|
+
|
|
159
|
+
fn render_leaf(
|
|
160
|
+
spec: &ControlSpec,
|
|
161
|
+
raw_config: &serde_json::Map<String, serde_json::Value>,
|
|
162
|
+
on_change: &Callback<crate::config::ColumnConfigFieldUpdate>,
|
|
163
|
+
) -> Option<Html> {
|
|
164
|
+
match spec.clone() {
|
|
165
|
+
ControlSpec::Enum {
|
|
166
|
+
key,
|
|
167
|
+
variants,
|
|
168
|
+
default,
|
|
169
|
+
} => {
|
|
170
|
+
let current = raw_config
|
|
171
|
+
.get(&key)
|
|
172
|
+
.and_then(|v| v.as_str().map(|s| s.to_string()));
|
|
173
|
+
Some(html! {
|
|
174
|
+
<EnumField
|
|
175
|
+
field_key={key}
|
|
176
|
+
{variants}
|
|
177
|
+
{default}
|
|
178
|
+
{current}
|
|
179
|
+
on_change={on_change.clone()}
|
|
180
|
+
/>
|
|
181
|
+
})
|
|
182
|
+
},
|
|
183
|
+
ControlSpec::Bool { key, default } => {
|
|
184
|
+
let current = raw_config.get(&key).and_then(|v| v.as_bool());
|
|
185
|
+
Some(html! {
|
|
186
|
+
<BoolField field_key={key} {default} {current} on_change={on_change.clone()} />
|
|
187
|
+
})
|
|
188
|
+
},
|
|
189
|
+
ControlSpec::Color { key, default } => {
|
|
190
|
+
let current = raw_config
|
|
191
|
+
.get(&key)
|
|
192
|
+
.and_then(|v| v.as_str().map(|s| s.to_string()));
|
|
193
|
+
Some(html! {
|
|
194
|
+
<ColorField field_key={key} {default} {current} on_change={on_change.clone()} />
|
|
195
|
+
})
|
|
196
|
+
},
|
|
197
|
+
ControlSpec::Number {
|
|
198
|
+
key,
|
|
199
|
+
default,
|
|
200
|
+
min,
|
|
201
|
+
max,
|
|
202
|
+
step,
|
|
203
|
+
include,
|
|
204
|
+
} => {
|
|
205
|
+
let current = raw_config.get(&key).and_then(|v| v.as_f64());
|
|
206
|
+
Some(html! {
|
|
207
|
+
<NumberFieldPrimitive
|
|
208
|
+
field_key={key}
|
|
209
|
+
{default}
|
|
210
|
+
{current}
|
|
211
|
+
{min}
|
|
212
|
+
{max}
|
|
213
|
+
{step}
|
|
214
|
+
{include}
|
|
215
|
+
on_change={on_change.clone()}
|
|
216
|
+
/>
|
|
217
|
+
})
|
|
218
|
+
},
|
|
219
|
+
ControlSpec::Group { .. }
|
|
220
|
+
| ControlSpec::AggregateDepth
|
|
221
|
+
| ControlSpec::NumberSeriesStyle { .. }
|
|
222
|
+
| ControlSpec::DatetimeFormat { .. }
|
|
223
|
+
| ControlSpec::StringFormat
|
|
224
|
+
| ControlSpec::Symbols { .. }
|
|
225
|
+
| ControlSpec::NumberFormat { .. }
|
|
226
|
+
| ControlSpec::String { .. }
|
|
227
|
+
| ControlSpec::Palette { .. }
|
|
228
|
+
| ControlSpec::GradientStops { .. } => None,
|
|
229
|
+
}
|
|
230
|
+
}
|
|
@@ -370,6 +370,7 @@ pub fn SettingsPanel(props: &SettingsPanelProps) -> Html {
|
|
|
370
370
|
<PluginTab
|
|
371
371
|
view_config={props.view_config.clone()}
|
|
372
372
|
plugin_config={props.plugin_config.clone()}
|
|
373
|
+
presentation={presentation.clone()}
|
|
373
374
|
renderer={renderer.clone()}
|
|
374
375
|
session={session.clone()}
|
|
375
376
|
// initial_width={width}
|
|
@@ -37,7 +37,7 @@ impl CustomNumberFormat {
|
|
|
37
37
|
min=1.
|
|
38
38
|
max=21.
|
|
39
39
|
step=1.
|
|
40
|
-
default=
|
|
40
|
+
default={ctx.props().defaults.minimum_integer_digits}
|
|
41
41
|
current_value={self.config.minimum_integer_digits}
|
|
42
42
|
on_change={ctx.link().callback(CustomNumberFormatMsg::MinimumIntegerDigits)}
|
|
43
43
|
/>
|
|
@@ -84,14 +84,23 @@ impl CustomNumberFormat {
|
|
|
84
84
|
}
|
|
85
85
|
|
|
86
86
|
fn float_section(&self, ctx: &yew::prelude::Context<Self>) -> yew::prelude::Html {
|
|
87
|
+
let defaults = &ctx.props().defaults;
|
|
87
88
|
let fractional_value = Some((
|
|
88
|
-
self.config
|
|
89
|
-
|
|
89
|
+
self.config
|
|
90
|
+
.minimum_fraction_digits
|
|
91
|
+
.unwrap_or(defaults.fraction.0),
|
|
92
|
+
self.config
|
|
93
|
+
.maximum_fraction_digits
|
|
94
|
+
.unwrap_or(defaults.fraction.1),
|
|
90
95
|
));
|
|
91
96
|
|
|
92
97
|
let significant_value = Some((
|
|
93
|
-
self.config
|
|
94
|
-
|
|
98
|
+
self.config
|
|
99
|
+
.minimum_significant_digits
|
|
100
|
+
.unwrap_or(defaults.significant.0),
|
|
101
|
+
self.config
|
|
102
|
+
.maximum_significant_digits
|
|
103
|
+
.unwrap_or(defaults.significant.1),
|
|
95
104
|
));
|
|
96
105
|
|
|
97
106
|
html! {
|
|
@@ -102,7 +111,7 @@ impl CustomNumberFormat {
|
|
|
102
111
|
min=0.
|
|
103
112
|
max=20.
|
|
104
113
|
step=1.
|
|
105
|
-
default={
|
|
114
|
+
default={defaults.fraction}
|
|
106
115
|
current_value={fractional_value}
|
|
107
116
|
on_change={ctx.link().callback(CustomNumberFormatMsg::FracChange)}
|
|
108
117
|
/>
|
|
@@ -113,7 +122,7 @@ impl CustomNumberFormat {
|
|
|
113
122
|
min=1.
|
|
114
123
|
max=21.
|
|
115
124
|
step=1.
|
|
116
|
-
default={
|
|
125
|
+
default={defaults.significant}
|
|
117
126
|
current_value={significant_value}
|
|
118
127
|
on_change={ctx.link().callback(CustomNumberFormatMsg::SigChange)}
|
|
119
128
|
/>
|
|
@@ -121,17 +130,20 @@ impl CustomNumberFormat {
|
|
|
121
130
|
{ self.rounding_increment(ctx) }
|
|
122
131
|
<SelectEnumField<RoundingPriority>
|
|
123
132
|
label="rounding-priority"
|
|
124
|
-
current_value={self.config.rounding_priority}
|
|
133
|
+
current_value={self.config.rounding_priority.unwrap_or(defaults.rounding_priority)}
|
|
134
|
+
default_value={defaults.rounding_priority}
|
|
125
135
|
on_change={ctx.link().callback(CustomNumberFormatMsg::RoundingPriority)}
|
|
126
136
|
/>
|
|
127
137
|
<SelectEnumField<RoundingMode>
|
|
128
138
|
label="rounding-mode"
|
|
129
|
-
current_value={self.config.rounding_mode}
|
|
139
|
+
current_value={self.config.rounding_mode.unwrap_or(defaults.rounding_mode)}
|
|
140
|
+
default_value={defaults.rounding_mode}
|
|
130
141
|
on_change={ctx.link().callback(CustomNumberFormatMsg::RoundingMode)}
|
|
131
142
|
/>
|
|
132
143
|
<SelectEnumField<TrailingZeroDisplay>
|
|
133
144
|
label="trailing-zero-display"
|
|
134
|
-
current_value={self.config.trailing_zero_display}
|
|
145
|
+
current_value={self.config.trailing_zero_display.unwrap_or(defaults.trailing_zero_display)}
|
|
146
|
+
default_value={defaults.trailing_zero_display}
|
|
135
147
|
on_change={ctx.link().callback(CustomNumberFormatMsg::TrailingZero)}
|
|
136
148
|
/>
|
|
137
149
|
</>
|
|
@@ -32,23 +32,27 @@ impl CustomNumberFormat {
|
|
|
32
32
|
None
|
|
33
33
|
};
|
|
34
34
|
|
|
35
|
+
let defaults = &ctx.props().defaults;
|
|
35
36
|
html! {
|
|
36
37
|
<>
|
|
37
38
|
<SelectEnumField<NotationName>
|
|
38
39
|
label="notation"
|
|
39
40
|
on_change={ctx.link().callback(CustomNumberFormatMsg::NotationChanged)}
|
|
40
41
|
current_value={self.notation.unwrap_or_default()}
|
|
42
|
+
default_value={NotationName::from(&defaults.notation)}
|
|
41
43
|
/>
|
|
42
44
|
{ compact_display_checkbox }
|
|
43
45
|
<SelectEnumField<UseGrouping>
|
|
44
46
|
label="use-grouping"
|
|
45
47
|
on_change={ctx.link().callback(CustomNumberFormatMsg::UseGrouping)}
|
|
46
|
-
current_value={self.config.use_grouping.
|
|
48
|
+
current_value={self.config.use_grouping.unwrap_or(defaults.use_grouping)}
|
|
49
|
+
default_value={defaults.use_grouping}
|
|
47
50
|
/>
|
|
48
51
|
<SelectEnumField<SignDisplay>
|
|
49
52
|
label="sign-display"
|
|
50
53
|
on_change={ctx.link().callback(CustomNumberFormatMsg::SignDisplay)}
|
|
51
|
-
current_value={self.config.sign_display.
|
|
54
|
+
current_value={self.config.sign_display.unwrap_or(defaults.sign_display)}
|
|
55
|
+
default_value={defaults.sign_display}
|
|
52
56
|
/>
|
|
53
57
|
</>
|
|
54
58
|
}
|
|
@@ -60,6 +60,7 @@ impl CustomNumberFormat {
|
|
|
60
60
|
<SelectEnumField<NumberStyle>
|
|
61
61
|
label="style"
|
|
62
62
|
current_value={self.style}
|
|
63
|
+
default_value={NumberStyle::from(&ctx.props().defaults.style)}
|
|
63
64
|
on_change={ctx.link().callback(CustomNumberFormatMsg::StyleChanged)}
|
|
64
65
|
/>
|
|
65
66
|
{ section }
|
|
@@ -12,6 +12,8 @@
|
|
|
12
12
|
|
|
13
13
|
use strum::{Display, EnumIter};
|
|
14
14
|
|
|
15
|
+
use crate::config::{Notation, NumberFormatStyle};
|
|
16
|
+
|
|
15
17
|
#[derive(Clone, PartialEq, Debug, Copy, Default, EnumIter, Display)]
|
|
16
18
|
pub enum NumberStyle {
|
|
17
19
|
#[default]
|
|
@@ -21,6 +23,17 @@ pub enum NumberStyle {
|
|
|
21
23
|
Unit,
|
|
22
24
|
}
|
|
23
25
|
|
|
26
|
+
impl From<&NumberFormatStyle> for NumberStyle {
|
|
27
|
+
fn from(style: &NumberFormatStyle) -> Self {
|
|
28
|
+
match style {
|
|
29
|
+
NumberFormatStyle::Decimal => Self::Decimal,
|
|
30
|
+
NumberFormatStyle::Currency(_) => Self::Currency,
|
|
31
|
+
NumberFormatStyle::Percent => Self::Percent,
|
|
32
|
+
NumberFormatStyle::Unit(_) => Self::Unit,
|
|
33
|
+
}
|
|
34
|
+
}
|
|
35
|
+
}
|
|
36
|
+
|
|
24
37
|
#[derive(Clone, PartialEq, Debug, Copy, Default, Display, EnumIter)]
|
|
25
38
|
pub enum NotationName {
|
|
26
39
|
#[default]
|
|
@@ -29,3 +42,14 @@ pub enum NotationName {
|
|
|
29
42
|
Engineering,
|
|
30
43
|
Compact,
|
|
31
44
|
}
|
|
45
|
+
|
|
46
|
+
impl From<&Notation> for NotationName {
|
|
47
|
+
fn from(notation: &Notation) -> Self {
|
|
48
|
+
match notation {
|
|
49
|
+
Notation::Standard => Self::Standard,
|
|
50
|
+
Notation::Scientific => Self::Scientific,
|
|
51
|
+
Notation::Engineering => Self::Engineering,
|
|
52
|
+
Notation::Compact(_) => Self::Compact,
|
|
53
|
+
}
|
|
54
|
+
}
|
|
55
|
+
}
|