Merge pull request #1731 from gavin-ts/grid-container-width-height

always allow width/height on grid containers
This commit is contained in:
gavin-ts 2023-11-14 21:33:40 -08:00 committed by GitHub
commit e5b3bc28f0
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
9 changed files with 784 additions and 18 deletions

View file

@ -11,6 +11,7 @@
- All vars defined in a scope are accessible everywhere in that scope, i.e., an object can use a var defined after itself. [#1695](https://github.com/terrastruct/d2/pull/1695) - All vars defined in a scope are accessible everywhere in that scope, i.e., an object can use a var defined after itself. [#1695](https://github.com/terrastruct/d2/pull/1695)
- Encoding API switches to standard zlib encoding so that decoding doesn't depend on source. [#1709](https://github.com/terrastruct/d2/pull/1709) - Encoding API switches to standard zlib encoding so that decoding doesn't depend on source. [#1709](https://github.com/terrastruct/d2/pull/1709)
- `currentcolor` is accepted as a color option to inherit parent colors. (ty @hboomsma) [#1700](https://github.com/terrastruct/d2/pull/1700) - `currentcolor` is accepted as a color option to inherit parent colors. (ty @hboomsma) [#1700](https://github.com/terrastruct/d2/pull/1700)
- grid containers can now be sized with `width`/`height` even when using a layout plugin without that feature. [#1731](https://github.com/terrastruct/d2/pull/1731)
#### Bugfixes ⛑️ #### Bugfixes ⛑️

View file

@ -5,6 +5,7 @@ import (
"context" "context"
"fmt" "fmt"
"math" "math"
"strconv"
"oss.terrastruct.com/d2/d2graph" "oss.terrastruct.com/d2/d2graph"
"oss.terrastruct.com/d2/d2target" "oss.terrastruct.com/d2/d2target"
@ -47,15 +48,7 @@ func Layout(ctx context.Context, g *d2graph.Graph) error {
verticalPadding = gd.verticalGap verticalPadding = gd.verticalGap
} }
// size shape according to grid contentWidth, contentHeight := gd.width, gd.height
obj.SizeToContent(gd.width, gd.height, float64(2*horizontalPadding), float64(2*verticalPadding))
// compute where the grid should be placed inside shape
s := obj.ToShape()
innerBox := s.GetInnerBox()
if innerBox.TopLeft.X != 0 || innerBox.TopLeft.Y != 0 {
gd.shift(innerBox.TopLeft.X, innerBox.TopLeft.Y)
}
var labelPosition, iconPosition label.Position var labelPosition, iconPosition label.Position
if obj.LabelPosition != nil { if obj.LabelPosition != nil {
@ -83,7 +76,7 @@ func Layout(ctx context.Context, g *d2graph.Graph) error {
label.InsideTopLeft, label.InsideTopCenter, label.InsideTopRight, label.InsideTopLeft, label.InsideTopCenter, label.InsideTopRight,
label.InsideBottomLeft, label.InsideBottomCenter, label.InsideBottomRight, label.InsideBottomLeft, label.InsideBottomCenter, label.InsideBottomRight,
label.OutsideBottomLeft, label.OutsideBottomCenter, label.OutsideBottomRight: label.OutsideBottomLeft, label.OutsideBottomCenter, label.OutsideBottomRight:
overflow := labelWidth - (obj.Width - float64(2*horizontalPadding)) overflow := labelWidth - contentWidth
if overflow > 0 { if overflow > 0 {
padding.Left += overflow / 2 padding.Left += overflow / 2
padding.Right += overflow / 2 padding.Right += overflow / 2
@ -95,7 +88,7 @@ func Layout(ctx context.Context, g *d2graph.Graph) error {
case label.OutsideLeftTop, label.OutsideLeftMiddle, label.OutsideLeftBottom, case label.OutsideLeftTop, label.OutsideLeftMiddle, label.OutsideLeftBottom,
label.InsideMiddleLeft, label.InsideMiddleCenter, label.InsideMiddleRight, label.InsideMiddleLeft, label.InsideMiddleCenter, label.InsideMiddleRight,
label.OutsideRightTop, label.OutsideRightMiddle, label.OutsideRightBottom: label.OutsideRightTop, label.OutsideRightMiddle, label.OutsideRightBottom:
overflow := labelHeight - (obj.Height - float64(2*verticalPadding)) overflow := labelHeight - contentHeight
if overflow > 0 { if overflow > 0 {
padding.Top += overflow / 2 padding.Top += overflow / 2
padding.Bottom += overflow / 2 padding.Bottom += overflow / 2
@ -112,7 +105,7 @@ func Layout(ctx context.Context, g *d2graph.Graph) error {
padding.Left = math.Max(padding.Left, iconSize) padding.Left = math.Max(padding.Left, iconSize)
padding.Right = math.Max(padding.Right, iconSize) padding.Right = math.Max(padding.Right, iconSize)
minWidth := 2*iconSize + float64(obj.LabelDimensions.Width) + 2*label.PADDING minWidth := 2*iconSize + float64(obj.LabelDimensions.Width) + 2*label.PADDING
overflow := minWidth - (obj.Width - float64(2*horizontalPadding)) overflow := minWidth - contentWidth
if overflow > 0 { if overflow > 0 {
padding.Left = math.Max(padding.Left, overflow/2) padding.Left = math.Max(padding.Left, overflow/2)
padding.Right = math.Max(padding.Right, overflow/2) padding.Right = math.Max(padding.Right, overflow/2)
@ -121,24 +114,65 @@ func Layout(ctx context.Context, g *d2graph.Graph) error {
overflowTop := padding.Top - float64(verticalPadding) overflowTop := padding.Top - float64(verticalPadding)
if overflowTop > 0 { if overflowTop > 0 {
obj.Height += overflowTop contentHeight += overflowTop
dy += overflowTop dy += overflowTop
} }
overflowBottom := padding.Bottom - float64(verticalPadding) overflowBottom := padding.Bottom - float64(verticalPadding)
if overflowBottom > 0 { if overflowBottom > 0 {
obj.Height += overflowBottom contentHeight += overflowBottom
} }
overflowLeft := padding.Left - float64(horizontalPadding) overflowLeft := padding.Left - float64(horizontalPadding)
if overflowLeft > 0 { if overflowLeft > 0 {
obj.Width += overflowLeft contentWidth += overflowLeft
dx += overflowLeft dx += overflowLeft
} }
overflowRight := padding.Right - float64(horizontalPadding) overflowRight := padding.Right - float64(horizontalPadding)
if overflowRight > 0 { if overflowRight > 0 {
obj.Width += overflowRight contentWidth += overflowRight
} }
// we need to center children if we have to expand to fit the container label // manually handle desiredWidth/Height so we can center the grid
var desiredWidth, desiredHeight int
var originalWidthAttr, originalHeightAttr *d2graph.Scalar
if obj.WidthAttr != nil {
desiredWidth, _ = strconv.Atoi(obj.WidthAttr.Value)
// SizeToContent without desired width
originalWidthAttr = obj.WidthAttr
obj.WidthAttr = nil
}
if obj.HeightAttr != nil {
desiredHeight, _ = strconv.Atoi(obj.HeightAttr.Value)
originalHeightAttr = obj.HeightAttr
obj.HeightAttr = nil
}
// size shape according to grid
obj.SizeToContent(contentWidth, contentHeight, float64(2*horizontalPadding), float64(2*verticalPadding))
if originalWidthAttr != nil {
obj.WidthAttr = originalWidthAttr
}
if originalHeightAttr != nil {
obj.HeightAttr = originalHeightAttr
}
if desiredWidth > 0 {
ddx := float64(desiredWidth) - obj.Width
if ddx > 0 {
dx += ddx / 2
obj.Width = float64(desiredWidth)
}
}
if desiredHeight > 0 {
ddy := float64(desiredHeight) - obj.Height
if ddy > 0 {
dy += ddy / 2
obj.Height = float64(desiredHeight)
}
}
// compute where the grid should be placed inside shape
innerBox := obj.ToShape().GetInnerBox()
dx = innerBox.TopLeft.X + dx
dy = innerBox.TopLeft.Y + dy
if dx != 0 || dy != 0 { if dx != 0 || dy != 0 {
gd.shift(dx, dy) gd.shift(dx, dy)
} }

View file

@ -38,7 +38,8 @@ func FeatureSupportCheck(info *PluginInfo, g *d2graph.Graph) error {
return fmt.Errorf(`Object "%s" has attribute "top" and/or "left" set, but layout engine "%s" does not support locked positions. See https://d2lang.com/tour/layouts/#layout-specific-functionality for more.`, obj.AbsID(), info.Name) return fmt.Errorf(`Object "%s" has attribute "top" and/or "left" set, but layout engine "%s" does not support locked positions. See https://d2lang.com/tour/layouts/#layout-specific-functionality for more.`, obj.AbsID(), info.Name)
} }
} }
if (obj.WidthAttr != nil || obj.HeightAttr != nil) && len(obj.ChildrenArray) > 0 { if (obj.WidthAttr != nil || obj.HeightAttr != nil) &&
len(obj.ChildrenArray) > 0 && !obj.IsGridDiagram() {
if _, ok := featureMap[CONTAINER_DIMENSIONS]; !ok { if _, ok := featureMap[CONTAINER_DIMENSIONS]; !ok {
return fmt.Errorf(`Object "%s" has attribute "width" and/or "height" set, but layout engine "%s" does not support dimensions set on containers. See https://d2lang.com/tour/layouts/#layout-specific-functionality for more.`, obj.AbsID(), info.Name) return fmt.Errorf(`Object "%s" has attribute "width" and/or "height" set, but layout engine "%s" does not support dimensions set on containers. See https://d2lang.com/tour/layouts/#layout-specific-functionality for more.`, obj.AbsID(), info.Name)
} }

View file

@ -2869,6 +2869,7 @@ y: profits {
loadFromFile(t, "grid_edge_across_cell"), loadFromFile(t, "grid_edge_across_cell"),
loadFromFile(t, "nesting_power"), loadFromFile(t, "nesting_power"),
loadFromFile(t, "unfilled_triangle"), loadFromFile(t, "unfilled_triangle"),
loadFromFile(t, "grid_container_dimensions"),
loadFromFile(t, "grid_label_positions"), loadFromFile(t, "grid_label_positions"),
} }

View file

@ -0,0 +1,11 @@
grid: {
width: 200
height: 200
grid-gap: 0
grid-rows: 2
grid-columns: 2
a
b
c
d
}

View file

@ -0,0 +1,253 @@
{
"name": "",
"isFolderOnly": false,
"fontFamily": "SourceSansPro",
"shapes": [
{
"id": "grid",
"type": "rectangle",
"pos": {
"x": 0,
"y": 0
},
"width": 200,
"height": 200,
"opacity": 1,
"strokeDash": 0,
"strokeWidth": 2,
"borderRadius": 0,
"fill": "B4",
"stroke": "B1",
"shadow": false,
"3d": false,
"multiple": false,
"double-border": false,
"tooltip": "",
"link": "",
"icon": null,
"iconPosition": "",
"blend": false,
"fields": null,
"methods": null,
"columns": null,
"label": "grid",
"fontSize": 28,
"fontFamily": "DEFAULT",
"language": "",
"color": "N1",
"italic": false,
"bold": false,
"underline": false,
"labelWidth": 44,
"labelHeight": 36,
"labelPosition": "INSIDE_TOP_CENTER",
"zIndex": 0,
"level": 1
},
{
"id": "grid.a",
"type": "rectangle",
"pos": {
"x": 46,
"y": 57
},
"width": 53,
"height": 66,
"opacity": 1,
"strokeDash": 0,
"strokeWidth": 2,
"borderRadius": 0,
"fill": "B5",
"stroke": "B1",
"shadow": false,
"3d": false,
"multiple": false,
"double-border": false,
"tooltip": "",
"link": "",
"icon": null,
"iconPosition": "",
"blend": false,
"fields": null,
"methods": null,
"columns": null,
"label": "a",
"fontSize": 16,
"fontFamily": "DEFAULT",
"language": "",
"color": "N1",
"italic": false,
"bold": true,
"underline": false,
"labelWidth": 8,
"labelHeight": 21,
"labelPosition": "INSIDE_MIDDLE_CENTER",
"zIndex": 0,
"level": 2
},
{
"id": "grid.b",
"type": "rectangle",
"pos": {
"x": 99,
"y": 57
},
"width": 54,
"height": 66,
"opacity": 1,
"strokeDash": 0,
"strokeWidth": 2,
"borderRadius": 0,
"fill": "B5",
"stroke": "B1",
"shadow": false,
"3d": false,
"multiple": false,
"double-border": false,
"tooltip": "",
"link": "",
"icon": null,
"iconPosition": "",
"blend": false,
"fields": null,
"methods": null,
"columns": null,
"label": "b",
"fontSize": 16,
"fontFamily": "DEFAULT",
"language": "",
"color": "N1",
"italic": false,
"bold": true,
"underline": false,
"labelWidth": 8,
"labelHeight": 21,
"labelPosition": "INSIDE_MIDDLE_CENTER",
"zIndex": 0,
"level": 2
},
{
"id": "grid.c",
"type": "rectangle",
"pos": {
"x": 46,
"y": 123
},
"width": 53,
"height": 66,
"opacity": 1,
"strokeDash": 0,
"strokeWidth": 2,
"borderRadius": 0,
"fill": "B5",
"stroke": "B1",
"shadow": false,
"3d": false,
"multiple": false,
"double-border": false,
"tooltip": "",
"link": "",
"icon": null,
"iconPosition": "",
"blend": false,
"fields": null,
"methods": null,
"columns": null,
"label": "c",
"fontSize": 16,
"fontFamily": "DEFAULT",
"language": "",
"color": "N1",
"italic": false,
"bold": true,
"underline": false,
"labelWidth": 8,
"labelHeight": 21,
"labelPosition": "INSIDE_MIDDLE_CENTER",
"zIndex": 0,
"level": 2
},
{
"id": "grid.d",
"type": "rectangle",
"pos": {
"x": 99,
"y": 123
},
"width": 54,
"height": 66,
"opacity": 1,
"strokeDash": 0,
"strokeWidth": 2,
"borderRadius": 0,
"fill": "B5",
"stroke": "B1",
"shadow": false,
"3d": false,
"multiple": false,
"double-border": false,
"tooltip": "",
"link": "",
"icon": null,
"iconPosition": "",
"blend": false,
"fields": null,
"methods": null,
"columns": null,
"label": "d",
"fontSize": 16,
"fontFamily": "DEFAULT",
"language": "",
"color": "N1",
"italic": false,
"bold": true,
"underline": false,
"labelWidth": 9,
"labelHeight": 21,
"labelPosition": "INSIDE_MIDDLE_CENTER",
"zIndex": 0,
"level": 2
}
],
"connections": [],
"root": {
"id": "",
"type": "",
"pos": {
"x": 0,
"y": 0
},
"width": 0,
"height": 0,
"opacity": 0,
"strokeDash": 0,
"strokeWidth": 0,
"borderRadius": 0,
"fill": "N7",
"stroke": "",
"shadow": false,
"3d": false,
"multiple": false,
"double-border": false,
"tooltip": "",
"link": "",
"icon": null,
"iconPosition": "",
"blend": false,
"fields": null,
"methods": null,
"columns": null,
"label": "",
"fontSize": 0,
"fontFamily": "",
"language": "",
"color": "",
"italic": false,
"bold": false,
"underline": false,
"labelWidth": 0,
"labelHeight": 0,
"zIndex": 0,
"level": 0
}
}

View file

@ -0,0 +1,106 @@
<?xml version="1.0" encoding="utf-8"?><svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" d2Version="v0.6.1-HEAD" preserveAspectRatio="xMinYMin meet" viewBox="0 0 202 202"><svg id="d2-svg" class="d2-3242100033" width="202" height="202" viewBox="-1 -1 202 202"><rect x="-1.000000" y="-1.000000" width="202.000000" height="202.000000" rx="0.000000" class=" fill-N7" stroke-width="0" /><style type="text/css"><![CDATA[
.d2-3242100033 .text {
font-family: "d2-3242100033-font-regular";
}
@font-face {
font-family: d2-3242100033-font-regular;
src: url("data:application/font-woff;base64,d09GRgABAAAAAAiIAAoAAAAADbQAAguFAAAAAAAAAAAAAAAAAAAAAAAAAABPUy8yAAAA9AAAAGAAAABgXd/Vo2NtYXAAAAFUAAAASgAAAFQBFQE2Z2x5ZgAAAaAAAALlAAADZP/8zIdoZWFkAAAEiAAAADYAAAA2G4Ue32hoZWEAAATAAAAAJAAAACQKhAXMaG10eAAABOQAAAAoAAAAKA/hAhtsb2NhAAAFDAAAABYAAAAWBdAEyG1heHAAAAUkAAAAIAAAACAAIgD2bmFtZQAABUQAAAMjAAAIFAbDVU1wb3N0AAAIaAAAAB0AAAAg/9EAMgADAgkBkAAFAAACigJYAAAASwKKAlgAAAFeADIBIwAAAgsFAwMEAwICBGAAAvcAAAADAAAAAAAAAABBREJPAEAAIP//Au7/BgAAA9gBESAAAZ8AAAAAAeYClAAAACAAA3icNMu5CYBAFADRt4cHYmG2IQhiai+Gip1+QdiJJnlIioRZtWAyyrLN7nBGYG0fbzxxx/WLVpIVVac38AEAAP//AQAA//88jw5CAAB4nEySTWgjZRiA329mOuPa1HaS+UvMZP7amSZxk81MZiZJJ0k3Tcq2RptNGmxc6LJWiKAuuoKlIPbi30X00JtXL56kCL14Kwj14lEQPHgKBT2FIIJ0RjJpi6eZw/d+D8/zfjAHAwDMxk4AhzuwCFFgASxaoVcUw9Ao13JdjcddA9HUAP3uf43QVpFwHKLQ+LNxdHyM9j7GTq7eqXwyHP60f3jofzm69E30yyVgUAwm6BSNIQHLALyq20XHLeq6ppKU4TiWybG0ZmgkaZiOa5Mky3Dn1YdffUNnVzPboqweVAadJoWrDzmtph09MSNb9zt9WippMlPm0u8+8n+tJDMNVfp80cunVwCDbjBB/2IXEAMZYE7VDY3SaIulZiwmBNnFkM9yHEqrWzJONbqYsrP6+I21x5vezlpLWtfkekQRTezifE80Pnu/92GtNXy9c6DKQZIHAECQCyboezSGZEiZak0BPBWqTTUs03F5kkTR9be8+2/X7rXiGTYvvtQyehtqhVtWOhHvWaf7zFN5Jybk+6XeUGRcUQHAIB9M0G83DrNm4eWGbd3Ecu1b0D+Pnq49cTM1meg1KTzZjq97Ujll1PXNyKdHOx/UUonej1elcjLd2vCTfL5Xeu0AcLgbyOgvNIYCVOGV283Y+v8+IdNiNS7spqnGzOu6I37TkWW42OxfU/XZmb8H7+lKNK7GBMPcLTDLC9+9SfP3OqahLkRXCvv9vve0nal62axXdTZ3rfzuC8pSQnj5j2ZdKnPE/GpSyi0QTDNrv5qh5upLtlRsp+n5Fxk+5VbvtvPotG7bnmfbdf+Lqq4mCCKWYY0cQBBACwB+wM4wHZ4DABLufDTbVxcA7aMx0NN3bfHW1O56WxTdbVJ4/EFa5JcizKK0EUejvZzz/AOCMGv+xe08fItGgIfzdLeLRn4CUPAztg0udgbzAHTYcJZHkCRBkCRsW4wLqZQQF+E/AAAA//8BAAD///qHrcsAAAAAAQAAAAILhWLUJa1fDzz1AAMD6AAAAADYXaChAAAAAN1mLzb+Ov7bCG8DyAAAAAMAAgAAAAAAAAABAAAD2P7vAAAImP46/joIbwABAAAAAAAAAAAAAAAAAAAACgKNAFkB+AA0AikAUgHIAC4CKwAvAfgALQD2AEUBWwBSAPYAUgAA/8kAAAAsAGQAmADGAPgBZAFwAZABnAGyAAAAAQAAAAoAjAAMAGYABwABAAAAAAAAAAAAAAAAAAQAA3icnJTdThtXFIU/B9ttVDUXFYrIDTqXbZWM3QiiBK5MCYpVhFOP0x+pqjR4xj9iPDPyDFCqPkCv+xZ9i1z1OfoQVa+rs7wNNqoUgRCwzpy991lnr7UPsMm/bFCrPwT+av5guMZ2c8/wAx41nxre4Ljxt+H6SkyDuPGb4SZfNvqGP+J9/Q/DH7NT/9nwQ7bqR4Y/4Xl90/CnG45/DD9ih/cLXIOX/G64xhaF4Qds8pPhDR5jNWt1HtM23OAztg032QYGTKlImZIxxjFiyphz5iSUhCTMmTIiIcbRpUNKpa8ZkZBj/L9fI0Iq5kSqOKHCkRKSElEysYq/KivnrU4caTW3vQ4VEyJOlXFGRIYjZ0xORsKZ6lRUFOzRokXJUHwLKkoCSqakBOTMGdOixxHHDJgwpcRxpEqeWUjOiIpLIp3vLMJ3ZkhCRmmszsmIxdOJX6LsLsc4ehSKXa18vFbhKY7vlO255Yr9ikC/boXZ+rlLNhEX6meqrqTauZSCE+36czt8K1yxh7tXf9aZfLhHsf5XqnzKufSPpVQmJhnObdEhlINC9wTHgdZdQnXke7oMeEOPdwy07tCnT4cTBnR5rdwefRxf0+OEQ2V0hRd7R3LMCT/i+IauYnztxPqzUCzhFwpzdymOc91jRqGee+aB7prohndX2M9QvuaOUjlDzZGPdNIv05xFjM0VhRjO1MulN0rrX2yOmOkuXtubfT8NFzZ7yym+ItcMe7cuOHnlFow+pGpwyzOX+gmIiMk5VcSQnBktKq7E+y0R56Q4DtW9N5qSis51jj/nSi5JmIlBl0x15hT6G5lvQuM+XPO9s7ckVr5nenZ9q/uc4tSrG43eqXvLvdC6nKwo0DJV8xU3DcU1M+8nmqlV/qFyS71uOc/ok0j1VDe4/Q48J6DNDrvsM9E5Q+1c2BvR1jvR5hX76sEZiaJGcnViFXYJeMEuu7zixVrNDocc0GP/DhwXWT0OeH1rZ12nZRVndf4Um7b4Op5dr17eW6/P7+DLLzRRNy9jX9r4bl9YtRv/nxAx81zc1uqd3BOC/wAAAP//AQAA//8HW0wwAHicYmBmAIP/5xiMGLAAAAAAAP//AQAA//8vAQIDAAAA");
}
.d2-3242100033 .text-bold {
font-family: "d2-3242100033-font-bold";
}
@font-face {
font-family: d2-3242100033-font-bold;
src: url("data:application/font-woff;base64,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");
}]]></style><style type="text/css"><![CDATA[.shape {
shape-rendering: geometricPrecision;
stroke-linejoin: round;
}
.connection {
stroke-linecap: round;
stroke-linejoin: round;
}
.blend {
mix-blend-mode: multiply;
opacity: 0.5;
}
.d2-3242100033 .fill-N1{fill:#0A0F25;}
.d2-3242100033 .fill-N2{fill:#676C7E;}
.d2-3242100033 .fill-N3{fill:#9499AB;}
.d2-3242100033 .fill-N4{fill:#CFD2DD;}
.d2-3242100033 .fill-N5{fill:#DEE1EB;}
.d2-3242100033 .fill-N6{fill:#EEF1F8;}
.d2-3242100033 .fill-N7{fill:#FFFFFF;}
.d2-3242100033 .fill-B1{fill:#0D32B2;}
.d2-3242100033 .fill-B2{fill:#0D32B2;}
.d2-3242100033 .fill-B3{fill:#E3E9FD;}
.d2-3242100033 .fill-B4{fill:#E3E9FD;}
.d2-3242100033 .fill-B5{fill:#EDF0FD;}
.d2-3242100033 .fill-B6{fill:#F7F8FE;}
.d2-3242100033 .fill-AA2{fill:#4A6FF3;}
.d2-3242100033 .fill-AA4{fill:#EDF0FD;}
.d2-3242100033 .fill-AA5{fill:#F7F8FE;}
.d2-3242100033 .fill-AB4{fill:#EDF0FD;}
.d2-3242100033 .fill-AB5{fill:#F7F8FE;}
.d2-3242100033 .stroke-N1{stroke:#0A0F25;}
.d2-3242100033 .stroke-N2{stroke:#676C7E;}
.d2-3242100033 .stroke-N3{stroke:#9499AB;}
.d2-3242100033 .stroke-N4{stroke:#CFD2DD;}
.d2-3242100033 .stroke-N5{stroke:#DEE1EB;}
.d2-3242100033 .stroke-N6{stroke:#EEF1F8;}
.d2-3242100033 .stroke-N7{stroke:#FFFFFF;}
.d2-3242100033 .stroke-B1{stroke:#0D32B2;}
.d2-3242100033 .stroke-B2{stroke:#0D32B2;}
.d2-3242100033 .stroke-B3{stroke:#E3E9FD;}
.d2-3242100033 .stroke-B4{stroke:#E3E9FD;}
.d2-3242100033 .stroke-B5{stroke:#EDF0FD;}
.d2-3242100033 .stroke-B6{stroke:#F7F8FE;}
.d2-3242100033 .stroke-AA2{stroke:#4A6FF3;}
.d2-3242100033 .stroke-AA4{stroke:#EDF0FD;}
.d2-3242100033 .stroke-AA5{stroke:#F7F8FE;}
.d2-3242100033 .stroke-AB4{stroke:#EDF0FD;}
.d2-3242100033 .stroke-AB5{stroke:#F7F8FE;}
.d2-3242100033 .background-color-N1{background-color:#0A0F25;}
.d2-3242100033 .background-color-N2{background-color:#676C7E;}
.d2-3242100033 .background-color-N3{background-color:#9499AB;}
.d2-3242100033 .background-color-N4{background-color:#CFD2DD;}
.d2-3242100033 .background-color-N5{background-color:#DEE1EB;}
.d2-3242100033 .background-color-N6{background-color:#EEF1F8;}
.d2-3242100033 .background-color-N7{background-color:#FFFFFF;}
.d2-3242100033 .background-color-B1{background-color:#0D32B2;}
.d2-3242100033 .background-color-B2{background-color:#0D32B2;}
.d2-3242100033 .background-color-B3{background-color:#E3E9FD;}
.d2-3242100033 .background-color-B4{background-color:#E3E9FD;}
.d2-3242100033 .background-color-B5{background-color:#EDF0FD;}
.d2-3242100033 .background-color-B6{background-color:#F7F8FE;}
.d2-3242100033 .background-color-AA2{background-color:#4A6FF3;}
.d2-3242100033 .background-color-AA4{background-color:#EDF0FD;}
.d2-3242100033 .background-color-AA5{background-color:#F7F8FE;}
.d2-3242100033 .background-color-AB4{background-color:#EDF0FD;}
.d2-3242100033 .background-color-AB5{background-color:#F7F8FE;}
.d2-3242100033 .color-N1{color:#0A0F25;}
.d2-3242100033 .color-N2{color:#676C7E;}
.d2-3242100033 .color-N3{color:#9499AB;}
.d2-3242100033 .color-N4{color:#CFD2DD;}
.d2-3242100033 .color-N5{color:#DEE1EB;}
.d2-3242100033 .color-N6{color:#EEF1F8;}
.d2-3242100033 .color-N7{color:#FFFFFF;}
.d2-3242100033 .color-B1{color:#0D32B2;}
.d2-3242100033 .color-B2{color:#0D32B2;}
.d2-3242100033 .color-B3{color:#E3E9FD;}
.d2-3242100033 .color-B4{color:#E3E9FD;}
.d2-3242100033 .color-B5{color:#EDF0FD;}
.d2-3242100033 .color-B6{color:#F7F8FE;}
.d2-3242100033 .color-AA2{color:#4A6FF3;}
.d2-3242100033 .color-AA4{color:#EDF0FD;}
.d2-3242100033 .color-AA5{color:#F7F8FE;}
.d2-3242100033 .color-AB4{color:#EDF0FD;}
.d2-3242100033 .color-AB5{color:#F7F8FE;}.appendix text.text{fill:#0A0F25}.md{--color-fg-default:#0A0F25;--color-fg-muted:#676C7E;--color-fg-subtle:#9499AB;--color-canvas-default:#FFFFFF;--color-canvas-subtle:#EEF1F8;--color-border-default:#0D32B2;--color-border-muted:#0D32B2;--color-neutral-muted:#EEF1F8;--color-accent-fg:#0D32B2;--color-accent-emphasis:#0D32B2;--color-attention-subtle:#676C7E;--color-danger-fg:red;}.sketch-overlay-B1{fill:url(#streaks-darker);mix-blend-mode:lighten}.sketch-overlay-B2{fill:url(#streaks-darker);mix-blend-mode:lighten}.sketch-overlay-B3{fill:url(#streaks-bright);mix-blend-mode:darken}.sketch-overlay-B4{fill:url(#streaks-bright);mix-blend-mode:darken}.sketch-overlay-B5{fill:url(#streaks-bright);mix-blend-mode:darken}.sketch-overlay-B6{fill:url(#streaks-bright);mix-blend-mode:darken}.sketch-overlay-AA2{fill:url(#streaks-dark);mix-blend-mode:overlay}.sketch-overlay-AA4{fill:url(#streaks-bright);mix-blend-mode:darken}.sketch-overlay-AA5{fill:url(#streaks-bright);mix-blend-mode:darken}.sketch-overlay-AB4{fill:url(#streaks-bright);mix-blend-mode:darken}.sketch-overlay-AB5{fill:url(#streaks-bright);mix-blend-mode:darken}.sketch-overlay-N1{fill:url(#streaks-darker);mix-blend-mode:lighten}.sketch-overlay-N2{fill:url(#streaks-dark);mix-blend-mode:overlay}.sketch-overlay-N3{fill:url(#streaks-normal);mix-blend-mode:color-burn}.sketch-overlay-N4{fill:url(#streaks-normal);mix-blend-mode:color-burn}.sketch-overlay-N5{fill:url(#streaks-bright);mix-blend-mode:darken}.sketch-overlay-N6{fill:url(#streaks-bright);mix-blend-mode:darken}.sketch-overlay-N7{fill:url(#streaks-bright);mix-blend-mode:darken}.light-code{display: block}.dark-code{display: none}]]></style><g id="grid"><g class="shape" ><rect x="0.000000" y="0.000000" width="200.000000" height="200.000000" class=" stroke-B1 fill-B4" style="stroke-width:2;" /></g><text x="100.000000" y="33.000000" class="text fill-N1" style="text-anchor:middle;font-size:28px">grid</text></g><g id="grid.a"><g class="shape" ><rect x="46.000000" y="57.000000" width="53.000000" height="66.000000" class=" stroke-B1 fill-B5" style="stroke-width:2;" /></g><text x="72.500000" y="95.500000" class="text-bold fill-N1" style="text-anchor:middle;font-size:16px">a</text></g><g id="grid.b"><g class="shape" ><rect x="99.000000" y="57.000000" width="54.000000" height="66.000000" class=" stroke-B1 fill-B5" style="stroke-width:2;" /></g><text x="126.000000" y="95.500000" class="text-bold fill-N1" style="text-anchor:middle;font-size:16px">b</text></g><g id="grid.c"><g class="shape" ><rect x="46.000000" y="123.000000" width="53.000000" height="66.000000" class=" stroke-B1 fill-B5" style="stroke-width:2;" /></g><text x="72.500000" y="161.500000" class="text-bold fill-N1" style="text-anchor:middle;font-size:16px">c</text></g><g id="grid.d"><g class="shape" ><rect x="99.000000" y="123.000000" width="54.000000" height="66.000000" class=" stroke-B1 fill-B5" style="stroke-width:2;" /></g><text x="126.000000" y="161.500000" class="text-bold fill-N1" style="text-anchor:middle;font-size:16px">d</text></g><mask id="d2-3242100033" maskUnits="userSpaceOnUse" x="-1" y="-1" width="202" height="202">
<rect x="-1" y="-1" width="202" height="202" fill="white"></rect>
<rect x="78.000000" y="5.000000" width="44" height="36" fill="rgba(0,0,0,0.75)"></rect>
<rect x="68.500000" y="79.500000" width="8" height="21" fill="rgba(0,0,0,0.75)"></rect>
<rect x="122.000000" y="79.500000" width="8" height="21" fill="rgba(0,0,0,0.75)"></rect>
<rect x="68.500000" y="145.500000" width="8" height="21" fill="rgba(0,0,0,0.75)"></rect>
<rect x="121.500000" y="145.500000" width="9" height="21" fill="rgba(0,0,0,0.75)"></rect>
</mask></svg></svg>

After

Width:  |  Height:  |  Size: 14 KiB

View file

@ -0,0 +1,253 @@
{
"name": "",
"isFolderOnly": false,
"fontFamily": "SourceSansPro",
"shapes": [
{
"id": "grid",
"type": "rectangle",
"pos": {
"x": 12,
"y": 12
},
"width": 200,
"height": 200,
"opacity": 1,
"strokeDash": 0,
"strokeWidth": 2,
"borderRadius": 0,
"fill": "B4",
"stroke": "B1",
"shadow": false,
"3d": false,
"multiple": false,
"double-border": false,
"tooltip": "",
"link": "",
"icon": null,
"iconPosition": "",
"blend": false,
"fields": null,
"methods": null,
"columns": null,
"label": "grid",
"fontSize": 28,
"fontFamily": "DEFAULT",
"language": "",
"color": "N1",
"italic": false,
"bold": false,
"underline": false,
"labelWidth": 44,
"labelHeight": 36,
"labelPosition": "INSIDE_TOP_CENTER",
"zIndex": 0,
"level": 1
},
{
"id": "grid.a",
"type": "rectangle",
"pos": {
"x": 58,
"y": 69
},
"width": 53,
"height": 66,
"opacity": 1,
"strokeDash": 0,
"strokeWidth": 2,
"borderRadius": 0,
"fill": "B5",
"stroke": "B1",
"shadow": false,
"3d": false,
"multiple": false,
"double-border": false,
"tooltip": "",
"link": "",
"icon": null,
"iconPosition": "",
"blend": false,
"fields": null,
"methods": null,
"columns": null,
"label": "a",
"fontSize": 16,
"fontFamily": "DEFAULT",
"language": "",
"color": "N1",
"italic": false,
"bold": true,
"underline": false,
"labelWidth": 8,
"labelHeight": 21,
"labelPosition": "INSIDE_MIDDLE_CENTER",
"zIndex": 0,
"level": 2
},
{
"id": "grid.b",
"type": "rectangle",
"pos": {
"x": 111,
"y": 69
},
"width": 54,
"height": 66,
"opacity": 1,
"strokeDash": 0,
"strokeWidth": 2,
"borderRadius": 0,
"fill": "B5",
"stroke": "B1",
"shadow": false,
"3d": false,
"multiple": false,
"double-border": false,
"tooltip": "",
"link": "",
"icon": null,
"iconPosition": "",
"blend": false,
"fields": null,
"methods": null,
"columns": null,
"label": "b",
"fontSize": 16,
"fontFamily": "DEFAULT",
"language": "",
"color": "N1",
"italic": false,
"bold": true,
"underline": false,
"labelWidth": 8,
"labelHeight": 21,
"labelPosition": "INSIDE_MIDDLE_CENTER",
"zIndex": 0,
"level": 2
},
{
"id": "grid.c",
"type": "rectangle",
"pos": {
"x": 58,
"y": 135
},
"width": 53,
"height": 66,
"opacity": 1,
"strokeDash": 0,
"strokeWidth": 2,
"borderRadius": 0,
"fill": "B5",
"stroke": "B1",
"shadow": false,
"3d": false,
"multiple": false,
"double-border": false,
"tooltip": "",
"link": "",
"icon": null,
"iconPosition": "",
"blend": false,
"fields": null,
"methods": null,
"columns": null,
"label": "c",
"fontSize": 16,
"fontFamily": "DEFAULT",
"language": "",
"color": "N1",
"italic": false,
"bold": true,
"underline": false,
"labelWidth": 8,
"labelHeight": 21,
"labelPosition": "INSIDE_MIDDLE_CENTER",
"zIndex": 0,
"level": 2
},
{
"id": "grid.d",
"type": "rectangle",
"pos": {
"x": 111,
"y": 135
},
"width": 54,
"height": 66,
"opacity": 1,
"strokeDash": 0,
"strokeWidth": 2,
"borderRadius": 0,
"fill": "B5",
"stroke": "B1",
"shadow": false,
"3d": false,
"multiple": false,
"double-border": false,
"tooltip": "",
"link": "",
"icon": null,
"iconPosition": "",
"blend": false,
"fields": null,
"methods": null,
"columns": null,
"label": "d",
"fontSize": 16,
"fontFamily": "DEFAULT",
"language": "",
"color": "N1",
"italic": false,
"bold": true,
"underline": false,
"labelWidth": 9,
"labelHeight": 21,
"labelPosition": "INSIDE_MIDDLE_CENTER",
"zIndex": 0,
"level": 2
}
],
"connections": [],
"root": {
"id": "",
"type": "",
"pos": {
"x": 0,
"y": 0
},
"width": 0,
"height": 0,
"opacity": 0,
"strokeDash": 0,
"strokeWidth": 0,
"borderRadius": 0,
"fill": "N7",
"stroke": "",
"shadow": false,
"3d": false,
"multiple": false,
"double-border": false,
"tooltip": "",
"link": "",
"icon": null,
"iconPosition": "",
"blend": false,
"fields": null,
"methods": null,
"columns": null,
"label": "",
"fontSize": 0,
"fontFamily": "",
"language": "",
"color": "",
"italic": false,
"bold": false,
"underline": false,
"labelWidth": 0,
"labelHeight": 0,
"zIndex": 0,
"level": 0
}
}

View file

@ -0,0 +1,106 @@
<?xml version="1.0" encoding="utf-8"?><svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" d2Version="v0.6.1-HEAD" preserveAspectRatio="xMinYMin meet" viewBox="0 0 202 202"><svg id="d2-svg" class="d2-2921019823" width="202" height="202" viewBox="11 11 202 202"><rect x="11.000000" y="11.000000" width="202.000000" height="202.000000" rx="0.000000" class=" fill-N7" stroke-width="0" /><style type="text/css"><![CDATA[
.d2-2921019823 .text {
font-family: "d2-2921019823-font-regular";
}
@font-face {
font-family: d2-2921019823-font-regular;
src: url("data:application/font-woff;base64,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");
}
.d2-2921019823 .text-bold {
font-family: "d2-2921019823-font-bold";
}
@font-face {
font-family: d2-2921019823-font-bold;
src: url("data:application/font-woff;base64,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");
}]]></style><style type="text/css"><![CDATA[.shape {
shape-rendering: geometricPrecision;
stroke-linejoin: round;
}
.connection {
stroke-linecap: round;
stroke-linejoin: round;
}
.blend {
mix-blend-mode: multiply;
opacity: 0.5;
}
.d2-2921019823 .fill-N1{fill:#0A0F25;}
.d2-2921019823 .fill-N2{fill:#676C7E;}
.d2-2921019823 .fill-N3{fill:#9499AB;}
.d2-2921019823 .fill-N4{fill:#CFD2DD;}
.d2-2921019823 .fill-N5{fill:#DEE1EB;}
.d2-2921019823 .fill-N6{fill:#EEF1F8;}
.d2-2921019823 .fill-N7{fill:#FFFFFF;}
.d2-2921019823 .fill-B1{fill:#0D32B2;}
.d2-2921019823 .fill-B2{fill:#0D32B2;}
.d2-2921019823 .fill-B3{fill:#E3E9FD;}
.d2-2921019823 .fill-B4{fill:#E3E9FD;}
.d2-2921019823 .fill-B5{fill:#EDF0FD;}
.d2-2921019823 .fill-B6{fill:#F7F8FE;}
.d2-2921019823 .fill-AA2{fill:#4A6FF3;}
.d2-2921019823 .fill-AA4{fill:#EDF0FD;}
.d2-2921019823 .fill-AA5{fill:#F7F8FE;}
.d2-2921019823 .fill-AB4{fill:#EDF0FD;}
.d2-2921019823 .fill-AB5{fill:#F7F8FE;}
.d2-2921019823 .stroke-N1{stroke:#0A0F25;}
.d2-2921019823 .stroke-N2{stroke:#676C7E;}
.d2-2921019823 .stroke-N3{stroke:#9499AB;}
.d2-2921019823 .stroke-N4{stroke:#CFD2DD;}
.d2-2921019823 .stroke-N5{stroke:#DEE1EB;}
.d2-2921019823 .stroke-N6{stroke:#EEF1F8;}
.d2-2921019823 .stroke-N7{stroke:#FFFFFF;}
.d2-2921019823 .stroke-B1{stroke:#0D32B2;}
.d2-2921019823 .stroke-B2{stroke:#0D32B2;}
.d2-2921019823 .stroke-B3{stroke:#E3E9FD;}
.d2-2921019823 .stroke-B4{stroke:#E3E9FD;}
.d2-2921019823 .stroke-B5{stroke:#EDF0FD;}
.d2-2921019823 .stroke-B6{stroke:#F7F8FE;}
.d2-2921019823 .stroke-AA2{stroke:#4A6FF3;}
.d2-2921019823 .stroke-AA4{stroke:#EDF0FD;}
.d2-2921019823 .stroke-AA5{stroke:#F7F8FE;}
.d2-2921019823 .stroke-AB4{stroke:#EDF0FD;}
.d2-2921019823 .stroke-AB5{stroke:#F7F8FE;}
.d2-2921019823 .background-color-N1{background-color:#0A0F25;}
.d2-2921019823 .background-color-N2{background-color:#676C7E;}
.d2-2921019823 .background-color-N3{background-color:#9499AB;}
.d2-2921019823 .background-color-N4{background-color:#CFD2DD;}
.d2-2921019823 .background-color-N5{background-color:#DEE1EB;}
.d2-2921019823 .background-color-N6{background-color:#EEF1F8;}
.d2-2921019823 .background-color-N7{background-color:#FFFFFF;}
.d2-2921019823 .background-color-B1{background-color:#0D32B2;}
.d2-2921019823 .background-color-B2{background-color:#0D32B2;}
.d2-2921019823 .background-color-B3{background-color:#E3E9FD;}
.d2-2921019823 .background-color-B4{background-color:#E3E9FD;}
.d2-2921019823 .background-color-B5{background-color:#EDF0FD;}
.d2-2921019823 .background-color-B6{background-color:#F7F8FE;}
.d2-2921019823 .background-color-AA2{background-color:#4A6FF3;}
.d2-2921019823 .background-color-AA4{background-color:#EDF0FD;}
.d2-2921019823 .background-color-AA5{background-color:#F7F8FE;}
.d2-2921019823 .background-color-AB4{background-color:#EDF0FD;}
.d2-2921019823 .background-color-AB5{background-color:#F7F8FE;}
.d2-2921019823 .color-N1{color:#0A0F25;}
.d2-2921019823 .color-N2{color:#676C7E;}
.d2-2921019823 .color-N3{color:#9499AB;}
.d2-2921019823 .color-N4{color:#CFD2DD;}
.d2-2921019823 .color-N5{color:#DEE1EB;}
.d2-2921019823 .color-N6{color:#EEF1F8;}
.d2-2921019823 .color-N7{color:#FFFFFF;}
.d2-2921019823 .color-B1{color:#0D32B2;}
.d2-2921019823 .color-B2{color:#0D32B2;}
.d2-2921019823 .color-B3{color:#E3E9FD;}
.d2-2921019823 .color-B4{color:#E3E9FD;}
.d2-2921019823 .color-B5{color:#EDF0FD;}
.d2-2921019823 .color-B6{color:#F7F8FE;}
.d2-2921019823 .color-AA2{color:#4A6FF3;}
.d2-2921019823 .color-AA4{color:#EDF0FD;}
.d2-2921019823 .color-AA5{color:#F7F8FE;}
.d2-2921019823 .color-AB4{color:#EDF0FD;}
.d2-2921019823 .color-AB5{color:#F7F8FE;}.appendix text.text{fill:#0A0F25}.md{--color-fg-default:#0A0F25;--color-fg-muted:#676C7E;--color-fg-subtle:#9499AB;--color-canvas-default:#FFFFFF;--color-canvas-subtle:#EEF1F8;--color-border-default:#0D32B2;--color-border-muted:#0D32B2;--color-neutral-muted:#EEF1F8;--color-accent-fg:#0D32B2;--color-accent-emphasis:#0D32B2;--color-attention-subtle:#676C7E;--color-danger-fg:red;}.sketch-overlay-B1{fill:url(#streaks-darker);mix-blend-mode:lighten}.sketch-overlay-B2{fill:url(#streaks-darker);mix-blend-mode:lighten}.sketch-overlay-B3{fill:url(#streaks-bright);mix-blend-mode:darken}.sketch-overlay-B4{fill:url(#streaks-bright);mix-blend-mode:darken}.sketch-overlay-B5{fill:url(#streaks-bright);mix-blend-mode:darken}.sketch-overlay-B6{fill:url(#streaks-bright);mix-blend-mode:darken}.sketch-overlay-AA2{fill:url(#streaks-dark);mix-blend-mode:overlay}.sketch-overlay-AA4{fill:url(#streaks-bright);mix-blend-mode:darken}.sketch-overlay-AA5{fill:url(#streaks-bright);mix-blend-mode:darken}.sketch-overlay-AB4{fill:url(#streaks-bright);mix-blend-mode:darken}.sketch-overlay-AB5{fill:url(#streaks-bright);mix-blend-mode:darken}.sketch-overlay-N1{fill:url(#streaks-darker);mix-blend-mode:lighten}.sketch-overlay-N2{fill:url(#streaks-dark);mix-blend-mode:overlay}.sketch-overlay-N3{fill:url(#streaks-normal);mix-blend-mode:color-burn}.sketch-overlay-N4{fill:url(#streaks-normal);mix-blend-mode:color-burn}.sketch-overlay-N5{fill:url(#streaks-bright);mix-blend-mode:darken}.sketch-overlay-N6{fill:url(#streaks-bright);mix-blend-mode:darken}.sketch-overlay-N7{fill:url(#streaks-bright);mix-blend-mode:darken}.light-code{display: block}.dark-code{display: none}]]></style><g id="grid"><g class="shape" ><rect x="12.000000" y="12.000000" width="200.000000" height="200.000000" class=" stroke-B1 fill-B4" style="stroke-width:2;" /></g><text x="112.000000" y="45.000000" class="text fill-N1" style="text-anchor:middle;font-size:28px">grid</text></g><g id="grid.a"><g class="shape" ><rect x="58.000000" y="69.000000" width="53.000000" height="66.000000" class=" stroke-B1 fill-B5" style="stroke-width:2;" /></g><text x="84.500000" y="107.500000" class="text-bold fill-N1" style="text-anchor:middle;font-size:16px">a</text></g><g id="grid.b"><g class="shape" ><rect x="111.000000" y="69.000000" width="54.000000" height="66.000000" class=" stroke-B1 fill-B5" style="stroke-width:2;" /></g><text x="138.000000" y="107.500000" class="text-bold fill-N1" style="text-anchor:middle;font-size:16px">b</text></g><g id="grid.c"><g class="shape" ><rect x="58.000000" y="135.000000" width="53.000000" height="66.000000" class=" stroke-B1 fill-B5" style="stroke-width:2;" /></g><text x="84.500000" y="173.500000" class="text-bold fill-N1" style="text-anchor:middle;font-size:16px">c</text></g><g id="grid.d"><g class="shape" ><rect x="111.000000" y="135.000000" width="54.000000" height="66.000000" class=" stroke-B1 fill-B5" style="stroke-width:2;" /></g><text x="138.000000" y="173.500000" class="text-bold fill-N1" style="text-anchor:middle;font-size:16px">d</text></g><mask id="d2-2921019823" maskUnits="userSpaceOnUse" x="11" y="11" width="202" height="202">
<rect x="11" y="11" width="202" height="202" fill="white"></rect>
<rect x="90.000000" y="17.000000" width="44" height="36" fill="rgba(0,0,0,0.75)"></rect>
<rect x="80.500000" y="91.500000" width="8" height="21" fill="rgba(0,0,0,0.75)"></rect>
<rect x="134.000000" y="91.500000" width="8" height="21" fill="rgba(0,0,0,0.75)"></rect>
<rect x="80.500000" y="157.500000" width="8" height="21" fill="rgba(0,0,0,0.75)"></rect>
<rect x="133.500000" y="157.500000" width="9" height="21" fill="rgba(0,0,0,0.75)"></rect>
</mask></svg></svg>

After

Width:  |  Height:  |  Size: 14 KiB